diff --git a/.github/workflows/anchor.yml b/.github/workflows/anchor.yml index 926a95b98..bb7800d39 100644 --- a/.github/workflows/anchor.yml +++ b/.github/workflows/anchor.yml @@ -6,7 +6,9 @@ on: push: branches: - main + - anchor-1.0-final - anchor-1.0 + - fix-biome-errors pull_request: types: [opened, synchronize, reopened] branches: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 64c46c494..ba7e949a1 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -9,7 +9,9 @@ on: push: branches: - main + - anchor-1.0-final - anchor-1.0 + - fix-biome-errors pull_request: types: [opened, synchronize, reopened] branches: diff --git a/.github/workflows/solana-native.yml b/.github/workflows/solana-native.yml index 9d6331e05..71c415abc 100644 --- a/.github/workflows/solana-native.yml +++ b/.github/workflows/solana-native.yml @@ -6,6 +6,8 @@ on: push: branches: - main + - anchor-1.0-final + - fix-biome-errors pull_request: types: [opened, synchronize, reopened] branches: @@ -107,6 +109,7 @@ jobs: failed_projects: ${{ steps.set-failed.outputs.failed_projects }} steps: - uses: actions/checkout@v5 + - uses: pnpm/action-setup@v4 - name: Use Node.js uses: actions/setup-node@v5 with: @@ -192,8 +195,7 @@ jobs: # Make the script executable chmod +x build_and_test.sh - # Install pnpm - npm install --global pnpm + # pnpm is already installed via pnpm/action-setup - name: Setup Solana Stable uses: heyAyushh/setup-solana@v5.9 with: diff --git a/.github/workflows/solana-pinocchio.yml b/.github/workflows/solana-pinocchio.yml index 3215934cd..82b8238e8 100644 --- a/.github/workflows/solana-pinocchio.yml +++ b/.github/workflows/solana-pinocchio.yml @@ -6,6 +6,8 @@ on: push: branches: - main + - anchor-1.0-final + - fix-biome-errors pull_request: types: [opened, synchronize, reopened] branches: @@ -107,6 +109,7 @@ jobs: failed_projects: ${{ steps.set-failed.outputs.failed_projects }} steps: - uses: actions/checkout@v5 + - uses: pnpm/action-setup@v4 - name: Use Node.js uses: actions/setup-node@v5 with: @@ -192,8 +195,7 @@ jobs: # Make the script executable chmod +x build_and_test.sh - # Install pnpm - npm install --global pnpm + # pnpm is already installed via pnpm/action-setup - name: Setup Solana Stable uses: heyAyushh/setup-solana@v5.9 with: diff --git a/.github/workflows/typescript.yml b/.github/workflows/typescript.yml new file mode 100644 index 000000000..e6cf42a5d --- /dev/null +++ b/.github/workflows/typescript.yml @@ -0,0 +1,31 @@ +name: TypeScript + +on: + push: + branches: + - main + - anchor-1.0-final + - fix-biome-errors + pull_request: + types: [opened, synchronize, reopened] + branches: + - main + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + biome: + name: Biome check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + # --frozen-lockfile: fail if pnpm-lock.yaml is out of date + # --ignore-workspace: only install root deps, not all 94 subprojects + - run: pnpm install --frozen-lockfile --ignore-workspace + - run: pnpm run check diff --git a/.gitignore b/.gitignore index 8a05c56b2..4577cdc5b 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,9 @@ node_modules/ **/*/.anchor **/*/.DS_Store **/*/target -**/*/tests/fixtures +# Ignore test fixtures by default, but allow .so program binaries needed for LiteSVM tests +**/*/tests/fixtures/* +!**/*/tests/fixtures/*.so **/*.rs.bk **/*/test-ledger **/*/yarn.lock diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..88ca7c2bd --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true +} diff --git a/Cargo.lock b/Cargo.lock index 27895f8ef..f301e5c9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,11 @@ name = "account-data-anchor-program" version = "0.1.0" dependencies = [ "anchor-lang", + "borsh 1.6.1", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -93,28 +98,6 @@ dependencies = [ "solana-svm-feature-set", ] -[[package]] -name = "agave-precompiles" -version = "3.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58acc95455da4ba868f723d2170af9bb3009a3f430580aae359eecc9b057fb3f" -dependencies = [ - "agave-feature-set", - "bincode", - "digest 0.10.7", - "ed25519-dalek 1.0.1", - "libsecp256k1", - "openssl", - "sha3", - "solana-ed25519-program", - "solana-message 3.1.0", - "solana-precompile-error", - "solana-pubkey 3.0.0", - "solana-sdk-ids 3.1.0", - "solana-secp256k1-program", - "solana-secp256r1-program", -] - [[package]] name = "agave-reserved-account-keys" version = "3.1.11" @@ -210,9 +193,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anchor-attribute-access-control" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3db7f5f8a6b16fa2b6e1b0222e656249c3abedf052e3943babf248929571204" +checksum = "b972f5fbd02524c92e4eb487c3c648904572702670f3d6fc81aef5f1751b1569" dependencies = [ "proc-macro2", "quote", @@ -221,9 +204,9 @@ dependencies = [ [[package]] name = "anchor-attribute-account" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a12661acaba9866a5f2d8d8d46a1eed8b484f41dc9f94f808c3b07d35726816" +checksum = "9acfcb07a92084bcfa9f6cc49a5c2e8e0e986f25f4b7caa184b7a2c9c9e561c2" dependencies = [ "anchor-syn", "proc-macro2", @@ -233,9 +216,9 @@ dependencies = [ [[package]] name = "anchor-attribute-constant" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dff08bc0187aafc559da8f63b5adeab0bcdf97128765c72dd9a4861f70627fc" +checksum = "8f46cc38f819377f07663b8eb492a701427950065e79d2d7b622a782443deb7a" dependencies = [ "anchor-syn", "quote", @@ -244,9 +227,9 @@ dependencies = [ [[package]] name = "anchor-attribute-error" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2af8ce12fb8cf782a3e127d376698a4548a518e38b4686f9c439adce4730b48" +checksum = "9c34748789107c9838329e058ca7b253e67f37b39ceae5a0a6c8d99f5d1bf1fe" dependencies = [ "anchor-syn", "quote", @@ -255,9 +238,9 @@ dependencies = [ [[package]] name = "anchor-attribute-event" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338be5df076369b99585264aaa46c66229ead67568d61bd38c3ab0fa7a15e554" +checksum = "1a28a3e5eefa03d9c5ef02b2139198f652547d38dddafc9c5545152dfba54556" dependencies = [ "anchor-syn", "proc-macro2", @@ -267,9 +250,9 @@ dependencies = [ [[package]] name = "anchor-attribute-program" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5c4ec70cef4ef7e2d87b4e9c550f727a43d691d3d7f3e4d6b2e3bd530ae098d" +checksum = "dfaa03865053cb168bfc4debe5992be87f397aa027dd81b69a2e44f2e5bae1c5" dependencies = [ "anchor-lang-idl", "anchor-syn", @@ -282,9 +265,9 @@ dependencies = [ [[package]] name = "anchor-derive-accounts" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f610cb50e10e4c404cc774f20a4eb602b904f68ea04590f8b1eb22a1e28b33e5" +checksum = "eef330db08f9ceee45c18ef96b15b869883d280c0ab5c6ff5d2e2f6481da7911" dependencies = [ "anchor-syn", "quote", @@ -293,9 +276,9 @@ dependencies = [ [[package]] name = "anchor-derive-serde" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9ead49a9689493f8857a61dd1abf1d70eeeeb0683f8c1e09b015ab5bdd382d" +checksum = "e0e80ff4e3ddb8c85aafd37926335c28f820516311e7106e5b7482b42e798aaa" dependencies = [ "anchor-syn", "proc-macro-crate 3.5.0", @@ -306,9 +289,9 @@ dependencies = [ [[package]] name = "anchor-derive-space" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4d1372743444967347b60f9311d2ee54a630152fd1d6d805adebd7fcd72056" +checksum = "2672af0ef4dfd5f5b6199355867b580cd8b4048093ef5208dd2b441305c15b8b" dependencies = [ "proc-macro2", "quote", @@ -317,9 +300,9 @@ dependencies = [ [[package]] name = "anchor-lang" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254d0cb160ea5c4c6a8c2f847bbd0f384fef733ebc36ef8426ae95f1bfda5757" +checksum = "8de9dce227fa0c08be20fef008c5b04681e1e0a15cb396e9619a9a1f800ff6cd" dependencies = [ "anchor-attribute-access-control", "anchor-attribute-account", @@ -390,13 +373,18 @@ name = "anchor-realloc" version = "0.1.0" dependencies = [ "anchor-lang", + "borsh 1.6.1", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] name = "anchor-syn" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a855d34b1b0488f37ccc759c8bd4a696cd3a7bba8cb0734c2a965109f707da" +checksum = "c62f42cb7e348c033bd9bfba59979bcd66431c026ba23490af94045aa357a950" dependencies = [ "anyhow", "bs58", @@ -954,6 +942,10 @@ name = "carnival" version = "0.1.0" dependencies = [ "anchor-lang", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -994,6 +986,11 @@ name = "checking-accounts-anchor-program-example" version = "0.1.0" dependencies = [ "anchor-lang", + "borsh 1.6.1", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -1076,6 +1073,10 @@ name = "close-account-program" version = "0.1.0" dependencies = [ "anchor-lang", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -1181,6 +1182,11 @@ name = "counter_anchor" version = "0.1.0" dependencies = [ "anchor-lang", + "borsh 1.6.1", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -1228,6 +1234,10 @@ name = "create-system-account" version = "0.1.0" dependencies = [ "anchor-lang", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -1259,16 +1269,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "ctr" version = "0.9.2" @@ -1278,19 +1278,6 @@ dependencies = [ "cipher", ] -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1453,19 +1440,10 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", - "signature 2.2.0", + "signature", "spki", ] -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature 1.6.4", -] - [[package]] name = "ed25519" version = "2.2.3" @@ -1473,21 +1451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", - "signature 2.2.0", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek 3.2.0", - "ed25519 1.5.3", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "zeroize", + "signature", ] [[package]] @@ -1496,8 +1460,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ - "curve25519-dalek 4.1.3", - "ed25519 2.2.3", + "curve25519-dalek", + "ed25519", "rand_core 0.6.4", "serde", "sha2 0.10.9", @@ -1512,8 +1476,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b49a684b133c4980d7ee783936af771516011c8cd15f429dbda77245e282f03" dependencies = [ "derivation-path", - "ed25519-dalek 2.2.0", - "hmac 0.12.1", + "ed25519-dalek", + "hmac", "sha2 0.10.9", ] @@ -1715,21 +1679,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "generic-array" version = "0.14.7" @@ -1793,6 +1742,10 @@ name = "hand" version = "0.1.0" dependencies = [ "anchor-lang", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -1851,6 +1804,9 @@ name = "hello-solana-anchor" version = "0.1.0" dependencies = [ "anchor-lang", + "litesvm", + "solana-kite", + "solana-signer", ] [[package]] @@ -1874,16 +1830,6 @@ dependencies = [ "pinocchio-log", ] -[[package]] -name = "hmac" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - [[package]] name = "hmac" version = "0.12.1" @@ -1893,17 +1839,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "hmac-drbg" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" -dependencies = [ - "digest 0.9.0", - "generic-array", - "hmac 0.8.1", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -1992,7 +1927,7 @@ dependencies = [ "elliptic-curve", "once_cell", "sha2 0.10.9", - "signature 2.2.0", + "signature", ] [[package]] @@ -2021,6 +1956,10 @@ name = "lever" version = "0.1.0" dependencies = [ "anchor-lang", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -2038,14 +1977,12 @@ dependencies = [ "arrayref", "base64 0.12.3", "digest 0.9.0", - "hmac-drbg", "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", "rand 0.7.3", "serde", "sha2 0.9.9", - "typenum", ] [[package]] @@ -2103,12 +2040,11 @@ dependencies = [ [[package]] name = "litesvm" -version = "0.8.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a22c52e9daf4680aee15e84c877808d94bbd4f3f66cdd32e0ba059d930d581e4" +checksum = "347d8c652d592c618ac996f2ab21f8c0b0f2da3fbbca227a6887ee61bb75f2de" dependencies = [ "agave-feature-set", - "agave-precompiles", "agave-reserved-account-keys", "agave-syscalls", "ansi_term", @@ -2118,6 +2054,7 @@ dependencies = [ "log", "serde", "solana-account 3.4.0", + "solana-address 2.4.0", "solana-address-lookup-table-interface 3.0.1", "solana-bpf-loader-program", "solana-builtins", @@ -2126,6 +2063,7 @@ dependencies = [ "solana-compute-budget-instruction", "solana-epoch-rewards 3.0.1", "solana-epoch-schedule 3.0.0", + "solana-feature-gate-interface 3.1.0", "solana-fee", "solana-fee-structure", "solana-hash 3.1.0", @@ -2142,7 +2080,6 @@ dependencies = [ "solana-precompile-error", "solana-program-error 3.0.1", "solana-program-runtime", - "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", @@ -2338,54 +2275,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "openssl" -version = "0.10.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "openssl-src" -version = "300.5.5+3.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1787d533e03597a7934fd0a765f0d28e94ecc5fb7789f8053b1e699a56f709" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.112" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - [[package]] name = "parking_lot" version = "0.12.5" @@ -2435,6 +2324,10 @@ name = "pda-rent-payer" version = "0.1.0" dependencies = [ "anchor-lang", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -2555,12 +2448,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - [[package]] name = "polyval" version = "0.6.2" @@ -2614,6 +2501,10 @@ name = "processing-instructions" version = "0.1.0" dependencies = [ "anchor-lang", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -2700,6 +2591,11 @@ name = "program-derived-addresses-program" version = "0.1.0" dependencies = [ "anchor-lang", + "borsh 1.6.1", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -2912,6 +2808,11 @@ name = "rent-example" version = "0.1.0" dependencies = [ "anchor-lang", + "borsh 1.6.1", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -2952,7 +2853,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac 0.12.1", + "hmac", "subtle", ] @@ -3188,12 +3089,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - [[package]] name = "signature" version = "2.2.0" @@ -3301,7 +3196,7 @@ dependencies = [ "borsh 1.6.1", "bytemuck", "bytemuck_derive", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "five8 1.0.0", "five8_const 1.0.0", "rand 0.9.2", @@ -3651,7 +3546,7 @@ checksum = "9a9eaec815ed773919bc7269c027933fc2472d7b9876f68ea6f1281c7daa5278" dependencies = [ "bytemuck", "bytemuck_derive", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "solana-define-syscall 3.0.0", "subtle", "thiserror 2.0.18", @@ -3701,18 +3596,6 @@ dependencies = [ "uriparse", ] -[[package]] -name = "solana-ed25519-program" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1419197f1c06abf760043f6d64ba9d79a03ad5a43f18c7586471937122094da" -dependencies = [ - "bytemuck", - "bytemuck_derive", - "solana-instruction 3.3.0", - "solana-sdk-ids 3.1.0", -] - [[package]] name = "solana-epoch-info" version = "3.1.0" @@ -3865,9 +3748,17 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75ca9b5cbb6f500f7fd73db5bd95640f71a83f04d6121a0e59a43b202dca2731" dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-instruction 3.3.0", "solana-program-error 3.0.1", "solana-pubkey 4.1.0", + "solana-rent 4.1.0", "solana-sdk-ids 3.1.0", + "solana-system-interface 3.1.0", ] [[package]] @@ -4108,7 +3999,7 @@ version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "263d614c12aa267a3278703175fd6440552ca61bc960b5a02a4482720c53438b" dependencies = [ - "ed25519-dalek 2.2.0", + "ed25519-dalek", "ed25519-dalek-bip32", "five8 1.0.0", "five8_core 1.0.0", @@ -4121,6 +4012,25 @@ dependencies = [ "solana-signer", ] +[[package]] +name = "solana-kite" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c6774af93647a15b51e266bc76f558fba11fbfbe30131b50664e665a8fea55" +dependencies = [ + "litesvm", + "solana-account 3.4.0", + "solana-instruction 3.3.0", + "solana-keypair", + "solana-message 3.1.0", + "solana-program 3.0.0", + "solana-pubkey 3.0.0", + "solana-signer", + "solana-transaction", + "spl-associated-token-account", + "spl-token", +] + [[package]] name = "solana-last-restart-slot" version = "2.2.1" @@ -4707,7 +4617,7 @@ dependencies = [ "borsh 1.6.1", "bytemuck", "bytemuck_derive", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "five8 0.2.1", "five8_const 0.1.4", "getrandom 0.2.17", @@ -4886,20 +4796,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "solana-secp256k1-program" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad4cf8232f7aef9ff2dd95d701f63e3c11909dec2400def5c361be29d24291e7" -dependencies = [ - "digest 0.10.7", - "k256", - "serde", - "serde_derive", - "sha3", - "solana-signature", -] - [[package]] name = "solana-secp256k1-recover" version = "2.2.1" @@ -4922,18 +4818,6 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "solana-secp256r1-program" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445d8e12592631d76fc4dc57858bae66c9fd7cc838c306c62a472547fc9d0ce6" -dependencies = [ - "bytemuck", - "openssl", - "solana-instruction 3.3.0", - "solana-sdk-ids 3.1.0", -] - [[package]] name = "solana-seed-derivable" version = "3.0.0" @@ -4949,7 +4833,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc905b200a95f2ea9146e43f2a7181e3aeb55de6bc12afb36462d00a3c7310de" dependencies = [ - "hmac 0.12.1", + "hmac", "pbkdf2", "sha2 0.10.9", ] @@ -5060,7 +4944,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "132a93134f1262aa832f1849b83bec6c9945669b866da18661a427943b9e801e" dependencies = [ - "ed25519-dalek 2.2.0", + "ed25519-dalek", "five8 1.0.0", "rand 0.9.2", "serde", @@ -5291,6 +5175,21 @@ dependencies = [ "solana-pubkey 3.0.0", ] +[[package]] +name = "solana-system-interface" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a95a6f2e23ed861d6444ad4a6d6896c418d7d101b960787e65a8e33157cee81b" +dependencies = [ + "num-traits", + "serde", + "serde_derive", + "solana-address 2.4.0", + "solana-instruction 3.3.0", + "solana-msg 3.1.0", + "solana-program-error 3.0.1", +] + [[package]] name = "solana-system-program" version = "3.1.11" @@ -5595,7 +5494,7 @@ dependencies = [ "bincode", "bytemuck", "bytemuck_derive", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "getrandom 0.2.17", "itertools 0.12.1", "js-sys", @@ -5649,7 +5548,7 @@ dependencies = [ "bincode", "bytemuck", "bytemuck_derive", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "itertools 0.12.1", "merlin", "num-derive", @@ -5682,12 +5581,39 @@ dependencies = [ "der", ] +[[package]] +name = "spl-associated-token-account" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0242277e290c023de8826f504abcf9206b3cd4e18d9ace4ec59a698b2828e88b" +dependencies = [ + "borsh 1.6.1", + "num-derive", + "num-traits", + "solana-account-info 3.1.1", + "solana-cpi 3.1.0", + "solana-instruction 3.3.0", + "solana-msg 3.1.0", + "solana-program-entrypoint 3.1.1", + "solana-program-error 3.0.1", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids 3.1.0", + "solana-system-interface 2.0.0", + "solana-sysvar 3.1.1", + "spl-associated-token-account-interface", + "spl-token-2022-interface", + "spl-token-interface", + "thiserror 2.0.18", +] + [[package]] name = "spl-associated-token-account-interface" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6433917b60441d68d99a17e121d9db0ea15a9a69c0e5afa34649cf5ba12612f" dependencies = [ + "borsh 1.6.1", "solana-instruction 3.3.0", "solana-pubkey 3.0.0", ] @@ -5747,6 +5673,34 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "spl-token" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878b0183d51fcd8a53e1604f4c13321894cf53227e6773c529b0d03d499a8dfd" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-account-info 3.1.1", + "solana-cpi 3.1.0", + "solana-instruction 3.3.0", + "solana-msg 3.1.0", + "solana-program-entrypoint 3.1.1", + "solana-program-error 3.0.1", + "solana-program-memory 3.1.0", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids 3.1.0", + "solana-sysvar 3.1.1", + "spl-token-interface", + "thiserror 2.0.18", +] + [[package]] name = "spl-token-2022-interface" version = "2.1.0" @@ -5801,7 +5755,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0cd59fce3dc00f563c6fa364d67c3f200d278eae681f4dc250240afcfe044b1" dependencies = [ - "curve25519-dalek 4.1.3", + "curve25519-dalek", "solana-zk-sdk", "thiserror 2.0.18", ] @@ -6112,6 +6066,10 @@ name = "transfer-sol" version = "0.1.0" dependencies = [ "anchor-lang", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -6192,12 +6150,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" diff --git a/Cargo.toml b/Cargo.toml index 66c8b33cb..a0a7bcb2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,7 +83,7 @@ pinocchio-system = "0.5.0" pinocchio-pubkey = "0.3.0" # testing -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-pubkey = "3.0.0" diff --git a/README.md b/README.md index fbf57e865..e19d4b286 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Program Examples -## Onchain program examples for :anchor: Anchor, :crab: Native Rust, and :boy: Pinocchio. +## Onchain program examples for ⚓ Anchor, 🦀 Native Rust, and 🤥 Pinocchio. [![Anchor](https://github.com/solana-developers/program-examples/actions/workflows/anchor.yml/badge.svg?event=schedule)](https://github.com/solana-developers/program-examples/actions/workflows/anchor.yml) [![Native](https://github.com/solana-developers/program-examples/actions/workflows/solana-native.yml/badge.svg?event=schedule)](https://github.com/solana-developers/program-examples/actions/workflows/solana-native.yml) [![Pinocchio](https://github.com/solana-developers/program-examples/actions/workflows/solana-pinocchio.yml/badge.svg?event=schedule)](https://github.com/solana-developers/program-examples/actions/workflows/solana-pinocchio.yml) diff --git a/basics/account-data/anchor/Anchor.toml b/basics/account-data/anchor/Anchor.toml index b3e350150..da5743131 100644 --- a/basics/account-data/anchor/Anchor.toml +++ b/basics/account-data/anchor/Anchor.toml @@ -2,18 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false [programs.localnet] -account_data_anchor_program = "GpVcgWdgVErgLqsn8VYUch6EqDerMgNqoLSmGyKrd6MR" - -# [registry] section removed — no longer used in Anchor 1.0 +account_data_anchor_program = "77pvTicQMoPQXrf97tCtuzgPQuS69U5oYsU99LYdqyLF" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" -litesvm-test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/litesvm.test.ts" #For litesvm test +test = "cargo test" + +[hooks] diff --git a/basics/account-data/anchor/package.json b/basics/account-data/anchor/package.json deleted file mode 100644 index fcb292b38..000000000 --- a/basics/account-data/anchor/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "litesvm": "^0.3.3", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - }, - "type": "module" -} diff --git a/basics/account-data/anchor/pnpm-lock.yaml b/basics/account-data/anchor/pnpm-lock.yaml deleted file mode 100644 index fea07a0c0..000000000 --- a/basics/account-data/anchor/pnpm-lock.yaml +++ /dev/null @@ -1,1463 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/web3.js': - specifier: ^1.98.4 - version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - devDependencies: - '@types/bn.js': - specifier: ^5.1.0 - version: 5.1.5 - '@types/chai': - specifier: ^4.3.0 - version: 4.3.16 - '@types/mocha': - specifier: ^9.0.0 - version: 9.1.1 - chai: - specifier: ^4.3.4 - version: 4.4.1 - litesvm: - specifier: ^0.3.3 - version: 0.3.3(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - mocha: - specifier: ^9.0.3 - version: 9.2.2 - ts-mocha: - specifier: ^10.0.0 - version: 10.0.0(mocha@9.2.2) - typescript: - specifier: ^5.3.3 - version: 5.9.3 - -packages: - - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} - engines: {node: '>=10'} - peerDependencies: - '@solana/web3.js': ^1.69.0 - - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} - engines: {node: '>=17'} - - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} - engines: {node: '>=10'} - - '@babel/runtime@7.25.0': - resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==} - engines: {node: '>=6.9.0'} - - '@noble/curves@1.4.2': - resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} - - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - - '@noble/hashes@1.8.0': - resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} - engines: {node: ^14.21.3 || >=16} - - '@solana/buffer-layout@4.0.1': - resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} - engines: {node: '>=5.10'} - - '@solana/codecs-core@2.3.0': - resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==} - engines: {node: '>=20.18.0'} - peerDependencies: - typescript: '>=5.3.3' - - '@solana/codecs-numbers@2.3.0': - resolution: {integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==} - engines: {node: '>=20.18.0'} - peerDependencies: - typescript: '>=5.3.3' - - '@solana/errors@2.3.0': - resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==} - engines: {node: '>=20.18.0'} - hasBin: true - peerDependencies: - typescript: '>=5.3.3' - - '@solana/web3.js@1.98.4': - resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==} - - '@swc/helpers@0.5.12': - resolution: {integrity: sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==} - - '@types/bn.js@5.1.5': - resolution: {integrity: sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==} - - '@types/chai@4.3.16': - resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} - - '@types/connect@3.4.38': - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - - '@types/mocha@9.1.1': - resolution: {integrity: sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==} - - '@types/node@12.20.55': - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - - '@types/node@20.12.11': - resolution: {integrity: sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==} - - '@types/uuid@8.3.4': - resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} - - '@types/ws@7.4.7': - resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} - - '@types/ws@8.5.12': - resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} - - '@ungap/promise-all-settled@1.1.2': - resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} - - JSONStream@1.3.5: - resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} - hasBin: true - - agentkeepalive@4.5.0: - resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} - engines: {node: '>= 8.0.0'} - - ansi-colors@4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} - engines: {node: '>=6'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base-x@3.0.9: - resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} - - base-x@5.0.1: - resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - bn.js@5.2.2: - resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} - - borsh@0.7.0: - resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - - browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - - bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} - - bs58@6.0.0: - resolution: {integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - buffer-layout@1.2.2: - resolution: {integrity: sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==} - engines: {node: '>=4.5'} - - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - bufferutil@4.0.8: - resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} - engines: {node: '>=6.14.2'} - - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chalk@5.6.2: - resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - - chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - commander@14.0.2: - resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} - engines: {node: '>=20'} - - commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - cross-fetch@3.2.0: - resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} - - debug@4.3.3: - resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - - deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} - - delay@5.0.0: - resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} - engines: {node: '>=10'} - - diff@3.5.0: - resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} - engines: {node: '>=0.3.1'} - - diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - es6-promise@4.2.8: - resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} - - es6-promisify@5.0.0: - resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - - eyes@0.1.8: - resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} - engines: {node: '> 0.1.90'} - - fast-stable-stringify@1.0.0: - resolution: {integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==} - - fastestsmallesttextencoderdecoder@1.0.22: - resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} - - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob@7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} - - growl@1.10.5: - resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==} - engines: {node: '>=4.x'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - isomorphic-ws@4.0.1: - resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} - peerDependencies: - ws: '*' - - jayson@4.1.1: - resolution: {integrity: sha512-5ZWm4Q/0DHPyeMfAsrwViwUS2DMVsQgWh8bEEIVTkfb3DzHZ2L3G5WUnF+AKmGjjM9r1uAv73SaqC1/U4RL45w==} - engines: {node: '>=8'} - hasBin: true - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - - json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - - jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - - litesvm-darwin-arm64@0.3.3: - resolution: {integrity: sha512-81YimsV3ezWjWLgoKixsXfVznaaecbURE3RtECgNb6Din6Za03pKGKGEN4gkyecHkv8uoPaEZv5cl6ARsgeN1Q==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - litesvm-darwin-x64@0.3.3: - resolution: {integrity: sha512-pYietuU165Bl+2eDnVp2Eidiedfjt+pljyyBAfJPbYriaFyG577mU364NiNcsfQ8ZZWbe+ygIEAVq4Ol247+1g==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] - - litesvm-linux-arm64-musl@0.3.3: - resolution: {integrity: sha512-mkI15rWtNbaJxVFUfh+qnolqnDCZEqhwSZo/XZ48TZNsQ69vAqY00KhyFhTVJ+jeaYCAZTSNamuFIiRBxqVmNg==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [musl] - - litesvm-linux-x64-gnu@0.3.3: - resolution: {integrity: sha512-Qai2/E8Eq03w8VKnJDREyiWxwavjykW/H6onE179ayMnBjVVmkj5fN7XF50VV4z73kasx5bpDzBNK8fcaxMdzA==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [glibc] - - litesvm-linux-x64-musl@0.3.3: - resolution: {integrity: sha512-bpWZ2f506hbfu1y6bkmuZf+qqtnLDxggpOMTQbibjd+q6faEO3sETWwKGlIgHB99P8wyU+aXKwLSGQX2sJEw6Q==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [musl] - - litesvm@0.3.3: - resolution: {integrity: sha512-QHXjAIXzvG0uAMOza6aJcYl19yTKz3guwq/z0Zml4KnQxyQvPhjaBpUFc5sf2ey/NxMVdqFhoXmL02CXOOomjw==} - engines: {node: '>= 20'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@4.2.1: - resolution: {integrity: sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==} - engines: {node: '>=10'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - mocha@9.2.2: - resolution: {integrity: sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==} - engines: {node: '>= 12.0.0'} - hasBin: true - - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.1: - resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - - node-gyp-build@4.8.1: - resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} - hasBin: true - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - pako@2.1.0: - resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - rpc-websockets@9.0.2: - resolution: {integrity: sha512-YzggvfItxMY3Lwuax5rC18inhbjJv9Py7JXRHxTIi94JOLrqBsSsUUc5bbl5W6c11tXhdfpDPK0KzBhoGe8jjw==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - serialize-javascript@6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} - - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - superstruct@0.15.5: - resolution: {integrity: sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==} - - superstruct@2.0.2: - resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} - engines: {node: '>=14.0.0'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - text-encoding-utf-8@1.0.2: - resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} - - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - toml@3.0.0: - resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} - - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - ts-mocha@10.0.0: - resolution: {integrity: sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw==} - engines: {node: '>= 6.X.X'} - hasBin: true - peerDependencies: - mocha: ^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X - - ts-node@7.0.1: - resolution: {integrity: sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==} - engines: {node: '>=4.2.0'} - hasBin: true - - tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - utf-8-validate@5.0.10: - resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} - engines: {node: '>=6.14.2'} - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - workerpool@6.2.0: - resolution: {integrity: sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yargs-parser@20.2.4: - resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} - engines: {node: '>=10'} - - yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} - - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - - yn@2.0.0: - resolution: {integrity: sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==} - engines: {node: '>=4'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': - dependencies: - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - bn.js: 5.2.2 - buffer-layout: 1.2.2 - - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 - '@noble/hashes': 1.8.0 - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - bn.js: 5.2.2 - bs58: 4.0.1 - buffer-layout: 1.2.2 - camelcase: 6.3.0 - cross-fetch: 3.2.0 - eventemitter3: 4.0.7 - pako: 2.1.0 - superstruct: 0.15.5 - toml: 3.0.0 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - '@anchor-lang/errors@1.0.0-rc.5': {} - - '@babel/runtime@7.25.0': - dependencies: - regenerator-runtime: 0.14.1 - - '@noble/curves@1.4.2': - dependencies: - '@noble/hashes': 1.4.0 - - '@noble/hashes@1.4.0': {} - - '@noble/hashes@1.8.0': {} - - '@solana/buffer-layout@4.0.1': - dependencies: - buffer: 6.0.3 - - '@solana/codecs-core@2.3.0(typescript@5.9.3)': - dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - - '@solana/codecs-numbers@2.3.0(typescript@5.9.3)': - dependencies: - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - - '@solana/errors@2.3.0(typescript@5.9.3)': - dependencies: - chalk: 5.6.2 - commander: 14.0.2 - typescript: 5.9.3 - - '@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@babel/runtime': 7.25.0 - '@noble/curves': 1.4.2 - '@noble/hashes': 1.8.0 - '@solana/buffer-layout': 4.0.1 - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) - agentkeepalive: 4.5.0 - bn.js: 5.2.2 - borsh: 0.7.0 - bs58: 4.0.1 - buffer: 6.0.3 - fast-stable-stringify: 1.0.0 - jayson: 4.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) - node-fetch: 2.7.0 - rpc-websockets: 9.0.2 - superstruct: 2.0.2 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - '@swc/helpers@0.5.12': - dependencies: - tslib: 2.6.2 - - '@types/bn.js@5.1.5': - dependencies: - '@types/node': 20.12.11 - - '@types/chai@4.3.16': {} - - '@types/connect@3.4.38': - dependencies: - '@types/node': 20.12.11 - - '@types/json5@0.0.29': - optional: true - - '@types/mocha@9.1.1': {} - - '@types/node@12.20.55': {} - - '@types/node@20.12.11': - dependencies: - undici-types: 5.26.5 - - '@types/uuid@8.3.4': {} - - '@types/ws@7.4.7': - dependencies: - '@types/node': 20.12.11 - - '@types/ws@8.5.12': - dependencies: - '@types/node': 20.12.11 - - '@ungap/promise-all-settled@1.1.2': {} - - JSONStream@1.3.5: - dependencies: - jsonparse: 1.3.1 - through: 2.3.8 - - agentkeepalive@4.5.0: - dependencies: - humanize-ms: 1.2.1 - - ansi-colors@4.1.1: {} - - ansi-regex@5.0.1: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - argparse@2.0.1: {} - - arrify@1.0.1: {} - - assertion-error@1.1.0: {} - - balanced-match@1.0.2: {} - - base-x@3.0.9: - dependencies: - safe-buffer: 5.2.1 - - base-x@5.0.1: {} - - base64-js@1.5.1: {} - - binary-extensions@2.3.0: {} - - bn.js@5.2.2: {} - - borsh@0.7.0: - dependencies: - bn.js: 5.2.2 - bs58: 4.0.1 - text-encoding-utf-8: 1.0.2 - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - braces@3.0.2: - dependencies: - fill-range: 7.0.1 - - browser-stdout@1.3.1: {} - - bs58@4.0.1: - dependencies: - base-x: 3.0.9 - - bs58@6.0.0: - dependencies: - base-x: 5.0.1 - - buffer-from@1.1.2: {} - - buffer-layout@1.2.2: {} - - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - bufferutil@4.0.8: - dependencies: - node-gyp-build: 4.8.1 - optional: true - - camelcase@6.3.0: {} - - chai@4.4.1: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.3 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.0.8 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chalk@5.6.2: {} - - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 - - chokidar@3.5.3: - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - commander@14.0.2: {} - - commander@2.20.3: {} - - concat-map@0.0.1: {} - - cross-fetch@3.2.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - debug@4.3.3(supports-color@8.1.1): - dependencies: - ms: 2.1.2 - optionalDependencies: - supports-color: 8.1.1 - - decamelize@4.0.0: {} - - deep-eql@4.1.3: - dependencies: - type-detect: 4.0.8 - - delay@5.0.0: {} - - diff@3.5.0: {} - - diff@5.0.0: {} - - emoji-regex@8.0.0: {} - - es6-promise@4.2.8: {} - - es6-promisify@5.0.0: - dependencies: - es6-promise: 4.2.8 - - escalade@3.1.2: {} - - escape-string-regexp@4.0.0: {} - - eventemitter3@4.0.7: {} - - eventemitter3@5.0.1: {} - - eyes@0.1.8: {} - - fast-stable-stringify@1.0.0: {} - - fastestsmallesttextencoderdecoder@1.0.22: {} - - fill-range@7.0.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat@5.0.2: {} - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - get-caller-file@2.0.5: {} - - get-func-name@2.0.2: {} - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - growl@1.10.5: {} - - has-flag@4.0.0: {} - - he@1.2.0: {} - - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - - ieee754@1.2.1: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - is-plain-obj@2.1.0: {} - - is-unicode-supported@0.1.0: {} - - isexe@2.0.0: {} - - isomorphic-ws@4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)): - dependencies: - ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) - - jayson@4.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10): - dependencies: - '@types/connect': 3.4.38 - '@types/node': 12.20.55 - '@types/ws': 7.4.7 - JSONStream: 1.3.5 - commander: 2.20.3 - delay: 5.0.0 - es6-promisify: 5.0.0 - eyes: 0.1.8 - isomorphic-ws: 4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - json-stringify-safe: 5.0.1 - uuid: 8.3.2 - ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - json-stringify-safe@5.0.1: {} - - json5@1.0.2: - dependencies: - minimist: 1.2.8 - optional: true - - jsonparse@1.3.1: {} - - litesvm-darwin-arm64@0.3.3: - optional: true - - litesvm-darwin-x64@0.3.3: - optional: true - - litesvm-linux-arm64-musl@0.3.3: - optional: true - - litesvm-linux-x64-gnu@0.3.3: - optional: true - - litesvm-linux-x64-musl@0.3.3: - optional: true - - litesvm@0.3.3(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10): - dependencies: - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - bs58: 6.0.0 - fastestsmallesttextencoderdecoder: 1.0.22 - optionalDependencies: - litesvm-darwin-arm64: 0.3.3 - litesvm-darwin-x64: 0.3.3 - litesvm-linux-arm64-musl: 0.3.3 - litesvm-linux-x64-gnu: 0.3.3 - litesvm-linux-x64-musl: 0.3.3 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - - make-error@1.3.6: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@4.2.1: - dependencies: - brace-expansion: 1.1.11 - - minimist@1.2.8: {} - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - mocha@9.2.2: - dependencies: - '@ungap/promise-all-settled': 1.1.2 - ansi-colors: 4.1.1 - browser-stdout: 1.3.1 - chokidar: 3.5.3 - debug: 4.3.3(supports-color@8.1.1) - diff: 5.0.0 - escape-string-regexp: 4.0.0 - find-up: 5.0.0 - glob: 7.2.0 - growl: 1.10.5 - he: 1.2.0 - js-yaml: 4.1.0 - log-symbols: 4.1.0 - minimatch: 4.2.1 - ms: 2.1.3 - nanoid: 3.3.1 - serialize-javascript: 6.0.0 - strip-json-comments: 3.1.1 - supports-color: 8.1.1 - which: 2.0.2 - workerpool: 6.2.0 - yargs: 16.2.0 - yargs-parser: 20.2.4 - yargs-unparser: 2.0.0 - - ms@2.1.2: {} - - ms@2.1.3: {} - - nanoid@3.3.1: {} - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - - node-gyp-build@4.8.1: - optional: true - - normalize-path@3.0.0: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - pako@2.1.0: {} - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - pathval@1.1.1: {} - - picomatch@2.3.1: {} - - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - regenerator-runtime@0.14.1: {} - - require-directory@2.1.1: {} - - rpc-websockets@9.0.2: - dependencies: - '@swc/helpers': 0.5.12 - '@types/uuid': 8.3.4 - '@types/ws': 8.5.12 - buffer: 6.0.3 - eventemitter3: 5.0.1 - uuid: 8.3.2 - ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - safe-buffer@5.2.1: {} - - serialize-javascript@6.0.0: - dependencies: - randombytes: 2.1.0 - - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-bom@3.0.0: - optional: true - - strip-json-comments@3.1.1: {} - - superstruct@0.15.5: {} - - superstruct@2.0.2: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - text-encoding-utf-8@1.0.2: {} - - through@2.3.8: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - toml@3.0.0: {} - - tr46@0.0.3: {} - - ts-mocha@10.0.0(mocha@9.2.2): - dependencies: - mocha: 9.2.2 - ts-node: 7.0.1 - optionalDependencies: - tsconfig-paths: 3.15.0 - - ts-node@7.0.1: - dependencies: - arrify: 1.0.1 - buffer-from: 1.1.2 - diff: 3.5.0 - make-error: 1.3.6 - minimist: 1.2.8 - mkdirp: 0.5.6 - source-map-support: 0.5.21 - yn: 2.0.0 - - tsconfig-paths@3.15.0: - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - optional: true - - tslib@2.6.2: {} - - type-detect@4.0.8: {} - - typescript@5.9.3: {} - - undici-types@5.26.5: {} - - utf-8-validate@5.0.10: - dependencies: - node-gyp-build: 4.8.1 - optional: true - - uuid@8.3.2: {} - - webidl-conversions@3.0.1: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - workerpool@6.2.0: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrappy@1.0.2: {} - - ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - y18n@5.0.8: {} - - yargs-parser@20.2.4: {} - - yargs-unparser@2.0.0: - dependencies: - camelcase: 6.3.0 - decamelize: 4.0.0 - flat: 5.0.2 - is-plain-obj: 2.1.0 - - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.4 - - yn@2.0.0: {} - - yocto-queue@0.1.0: {} diff --git a/basics/account-data/anchor/programs/anchor-program-example/Cargo.toml b/basics/account-data/anchor/programs/anchor-program-example/Cargo.toml index 2d23f9606..0adedc17f 100644 --- a/basics/account-data/anchor/programs/anchor-program-example/Cargo.toml +++ b/basics/account-data/anchor/programs/anchor-program-example/Cargo.toml @@ -20,8 +20,14 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/account-data/anchor/programs/anchor-program-example/src/lib.rs b/basics/account-data/anchor/programs/anchor-program-example/src/lib.rs index 52ae01807..1221bc675 100644 --- a/basics/account-data/anchor/programs/anchor-program-example/src/lib.rs +++ b/basics/account-data/anchor/programs/anchor-program-example/src/lib.rs @@ -5,7 +5,7 @@ pub mod constants; pub mod instructions; pub mod state; -declare_id!("GpVcgWdgVErgLqsn8VYUch6EqDerMgNqoLSmGyKrd6MR"); +declare_id!("77pvTicQMoPQXrf97tCtuzgPQuS69U5oYsU99LYdqyLF"); #[program] pub mod account_data_anchor_program { diff --git a/basics/account-data/anchor/programs/anchor-program-example/tests/test_account_data.rs b/basics/account-data/anchor/programs/anchor-program-example/tests/test_account_data.rs new file mode 100644 index 000000000..df3bac0a0 --- /dev/null +++ b/basics/account-data/anchor/programs/anchor-program-example/tests/test_account_data.rs @@ -0,0 +1,66 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, system_program}, + AnchorSerialize, InstructionData, ToAccountMetas, + }, + borsh::BorshDeserialize, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +/// Deserialize the AddressInfo account (8-byte discriminator + fields). +#[derive(BorshDeserialize)] +struct AddressInfoAccount { + _discriminator: [u8; 8], + name: String, + house_number: u8, + street: String, + city: String, +} + +#[test] +fn test_create_address_info() { + let program_id = account_data_anchor_program::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/account_data_anchor_program.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let address_info_keypair = Keypair::new(); + + let instruction = Instruction::new_with_bytes( + program_id, + &account_data_anchor_program::instruction::CreateAddressInfo { + name: "Joe C".to_string(), + house_number: 136, + street: "Mile High Dr.".to_string(), + city: "Solana Beach".to_string(), + } + .data(), + account_data_anchor_program::accounts::CreateAddressInfo { + payer: payer.pubkey(), + address_info: address_info_keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &address_info_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Read the account data back + let account = svm.get_account(&address_info_keypair.pubkey()).unwrap(); + let info = AddressInfoAccount::deserialize(&mut &account.data[..]).unwrap(); + + assert_eq!(info.name, "Joe C"); + assert_eq!(info.house_number, 136); + assert_eq!(info.street, "Mile High Dr."); + assert_eq!(info.city, "Solana Beach"); +} diff --git a/basics/account-data/anchor/tests/litesvm.test.ts b/basics/account-data/anchor/tests/litesvm.test.ts deleted file mode 100644 index 2136f1caa..000000000 --- a/basics/account-data/anchor/tests/litesvm.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { BorshCoder } from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; -import { LiteSVM } from "litesvm"; - -import IDL from "../target/idl/account_data_anchor_program.json" with { - type: "json", -}; - -describe("Account Data!", () => { - let litesvm: LiteSVM; - let programId: PublicKey; - let payer: Keypair; - let addressInfoAccount: Keypair; - const coder = new BorshCoder(IDL); - - before(() => { - litesvm = new LiteSVM(); - programId = new PublicKey(IDL.address); - payer = Keypair.generate(); - addressInfoAccount = Keypair.generate(); - - const programPath = new URL( - "../target/deploy/account_data_anchor_program.so", - // @ts-ignore - import.meta.url, - ).pathname; - litesvm.addProgramFromFile(programId, programPath); - - litesvm.airdrop(payer.publicKey, BigInt(100000000000)); - }); - - it("Create the address info account", () => { - console.log(`Payer Address : ${payer.publicKey}`); - console.log(`Address Info Acct : ${addressInfoAccount.publicKey}`); - - // Instruction Ix data - const addressInfoIns = { - name: "Joe C", - house_number: 136, - street: "Mile High Dr.", - city: "Solana Beach", - }; - - /** - * Convert into buffer and encode of instruction and arguments - */ - const data = coder.instruction.encode( - "create_address_info", - addressInfoIns, - ); - - /** - * Create Transactions - */ - - const ix = new TransactionInstruction({ - keys: [ - { - pubkey: payer.publicKey, - isSigner: true, - isWritable: true, - }, - { - pubkey: addressInfoAccount.publicKey, - isSigner: true, - isWritable: true, - }, - { - pubkey: SystemProgram.programId, - isSigner: false, - isWritable: false, - }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = litesvm.latestBlockhash(); - tx.sign(payer, addressInfoAccount); - const res = litesvm.sendTransaction(tx); - // console.log(res.toString()); - }); - it("Read the new account's data", () => { - const accountInfoAcc = litesvm.getAccount(addressInfoAccount.publicKey); - if (!accountInfoAcc) { - throw new Error("Failed to fetch account info"); - } - - /** - * Decode the accounts' data - */ - const addressInfo = coder.accounts.decode( - "AddressInfo", - Buffer.from(accountInfoAcc.data), - ); - - console.log(`Name : ${addressInfo.name}`); - console.log(`House Num: ${addressInfo.house_number}`); - console.log(`Street : ${addressInfo.street}`); - console.log(`City : ${addressInfo.city}`); - }); -}); diff --git a/basics/account-data/anchor/tests/test.ts b/basics/account-data/anchor/tests/test.ts deleted file mode 100644 index b8822eabd..000000000 --- a/basics/account-data/anchor/tests/test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as anchor from "@anchor-lang/core"; -import { Keypair } from "@solana/web3.js"; -import type { AccountDataAnchorProgram } from "../target/types/account_data_anchor_program"; - -describe("Account Data!", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - const program = anchor.workspace - .AccountDataAnchorProgram as anchor.Program; - - // Generate a new keypair for the addressInfo account - const addressInfoAccount = new Keypair(); - - it("Create the address info account", async () => { - console.log(`Payer Address : ${payer.publicKey}`); - console.log(`Address Info Acct : ${addressInfoAccount.publicKey}`); - - // Instruction Ix data - const addressInfo = { - name: "Joe C", - houseNumber: 136, - street: "Mile High Dr.", - city: "Solana Beach", - }; - - await program.methods - .createAddressInfo( - addressInfo.name, - addressInfo.houseNumber, - addressInfo.street, - addressInfo.city, - ) - .accounts({ - addressInfo: addressInfoAccount.publicKey, - payer: payer.publicKey, - }) - .signers([addressInfoAccount]) - .rpc(); - }); - - it("Read the new account's data", async () => { - const addressInfo = await program.account.addressInfo.fetch( - addressInfoAccount.publicKey, - ); - console.log(`Name : ${addressInfo.name}`); - console.log(`House Num: ${addressInfo.houseNumber}`); - console.log(`Street : ${addressInfo.street}`); - console.log(`City : ${addressInfo.city}`); - }); -}); diff --git a/basics/account-data/anchor/tsconfig.json b/basics/account-data/anchor/tsconfig.json deleted file mode 100644 index cd5d2e3d0..000000000 --- a/basics/account-data/anchor/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], - "module": "commonjs", - "target": "es6", - "esModuleInterop": true - } -} diff --git a/basics/account-data/native/program/Cargo.toml b/basics/account-data/native/program/Cargo.toml index 968f41b7f..acdb1be45 100644 --- a/basics/account-data/native/program/Cargo.toml +++ b/basics/account-data/native/program/Cargo.toml @@ -20,7 +20,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-keypair = "3.0.1" solana-message = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/account-data/native/tests/test.ts b/basics/account-data/native/tests/test.ts index 3965804f5..5af298222 100644 --- a/basics/account-data/native/tests/test.ts +++ b/basics/account-data/native/tests/test.ts @@ -1,88 +1,76 @@ import { Buffer } from "node:buffer"; import { describe, test } from "node:test"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; import * as borsh from "borsh"; import { start } from "solana-bankrun"; const AddressInfoSchema = { - struct: { - name: "string", - house_number: "u8", - street: "string", - city: "string", - }, + struct: { + name: "string", + house_number: "u8", + street: "string", + city: "string", + }, }; type AddressInfo = { - name: string; - house_number: number; - street: string; - city: string; + name: string; + house_number: number; + street: string; + city: string; }; function borshSerialize(schema: borsh.Schema, data: object): Buffer { - return Buffer.from(borsh.serialize(schema, data)); + return Buffer.from(borsh.serialize(schema, data)); } describe("Account Data!", async () => { - const addressInfoAccount = Keypair.generate(); - const PROGRAM_ID = PublicKey.unique(); - const context = await start( - [{ name: "account_data_native_program", programId: PROGRAM_ID }], - [], - ); - const client = context.banksClient; + const addressInfoAccount = Keypair.generate(); + const PROGRAM_ID = PublicKey.unique(); + const context = await start([{ name: "account_data_native_program", programId: PROGRAM_ID }], []); + const client = context.banksClient; - test("Create the address info account", async () => { - const payer = context.payer; + test("Create the address info account", async () => { + const payer = context.payer; - console.log(`Program Address : ${PROGRAM_ID}`); - console.log(`Payer Address : ${payer.publicKey}`); - console.log(`Address Info Acct : ${addressInfoAccount.publicKey}`); + console.log(`Program Address : ${PROGRAM_ID}`); + console.log(`Payer Address : ${payer.publicKey}`); + console.log(`Address Info Acct : ${addressInfoAccount.publicKey}`); - const ix = new TransactionInstruction({ - keys: [ - { - pubkey: addressInfoAccount.publicKey, - isSigner: true, - isWritable: true, - }, - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId: PROGRAM_ID, - data: borshSerialize(AddressInfoSchema, { - name: "Joe C", - house_number: 136, - street: "Mile High Dr.", - city: "Solana Beach", - }), - }); + const ix = new TransactionInstruction({ + keys: [ + { + pubkey: addressInfoAccount.publicKey, + isSigner: true, + isWritable: true, + }, + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId: PROGRAM_ID, + data: borshSerialize(AddressInfoSchema, { + name: "Joe C", + house_number: 136, + street: "Mile High Dr.", + city: "Solana Beach", + }), + }); - const blockhash = context.lastBlockhash; + const blockhash = context.lastBlockhash; - const tx = new Transaction(); - tx.recentBlockhash = blockhash; - tx.add(ix).sign(payer, addressInfoAccount); - await client.processTransaction(tx); - }); + const tx = new Transaction(); + tx.recentBlockhash = blockhash; + tx.add(ix).sign(payer, addressInfoAccount); + await client.processTransaction(tx); + }); - test("Read the new account's data", async () => { - const accountInfo = await client.getAccount(addressInfoAccount.publicKey); + test("Read the new account's data", async () => { + const accountInfo = await client.getAccount(addressInfoAccount.publicKey); - const readAddressInfo = borsh.deserialize( - AddressInfoSchema, - Buffer.from(accountInfo.data), - ) as AddressInfo; - console.log(`Name : ${readAddressInfo.name}`); - console.log(`House Num: ${readAddressInfo.house_number}`); - console.log(`Street : ${readAddressInfo.street}`); - console.log(`City : ${readAddressInfo.city}`); - }); + const readAddressInfo = borsh.deserialize(AddressInfoSchema, Buffer.from(accountInfo.data)) as AddressInfo; + console.log(`Name : ${readAddressInfo.name}`); + console.log(`House Num: ${readAddressInfo.house_number}`); + console.log(`Street : ${readAddressInfo.street}`); + console.log(`City : ${readAddressInfo.city}`); + }); }); diff --git a/basics/account-data/pinocchio/program/Cargo.toml b/basics/account-data/pinocchio/program/Cargo.toml index c79283770..4239753c5 100644 --- a/basics/account-data/pinocchio/program/Cargo.toml +++ b/basics/account-data/pinocchio/program/Cargo.toml @@ -9,7 +9,7 @@ pinocchio-log.workspace = true pinocchio-system.workspace = true [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-keypair = "3.0.1" solana-message = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/account-data/pinocchio/tests/index.test.ts b/basics/account-data/pinocchio/tests/index.test.ts index 1fac4271e..825ab4e67 100644 --- a/basics/account-data/pinocchio/tests/index.test.ts +++ b/basics/account-data/pinocchio/tests/index.test.ts @@ -1,149 +1,142 @@ import { readFileSync } from "node:fs"; import { describe, test } from "node:test"; -import { - Keypair, - LAMPORTS_PER_SOL, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, LAMPORTS_PER_SOL, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; import { LiteSVM } from "litesvm"; interface AddressInfo { - name: string; - house_number: number; - street: string; - city: string; + name: string; + house_number: number; + street: string; + city: string; } function toBytes(addressInfo: AddressInfo): Buffer { - const data: number[] = []; + const data: number[] = []; - // Add instruction discriminator - data.push(0); + // Add instruction discriminator + data.push(0); - // Pad name to 16 bytes (data[1..17]) - const nameBytes = Buffer.from(addressInfo.name, "utf-8"); - const namePadded = Buffer.alloc(16); - nameBytes.copy(namePadded, 0, 0, Math.min(nameBytes.length, 16)); - data.push(...namePadded); + // Pad name to 16 bytes (data[1..17]) + const nameBytes = Buffer.from(addressInfo.name, "utf-8"); + const namePadded = Buffer.alloc(16); + nameBytes.copy(namePadded, 0, 0, Math.min(nameBytes.length, 16)); + data.push(...namePadded); - // Add 1 byte padding at index 17 - data.push(0); + // Add 1 byte padding at index 17 + data.push(0); - // Add house_number at index 18 - data.push(addressInfo.house_number); + // Add house_number at index 18 + data.push(addressInfo.house_number); - // Pad street to 16 bytes (data[19..35]) - const streetBytes = Buffer.from(addressInfo.street, "utf-8"); - const streetPadded = Buffer.alloc(16); - streetBytes.copy(streetPadded, 0, 0, Math.min(streetBytes.length, 16)); - data.push(...streetPadded); + // Pad street to 16 bytes (data[19..35]) + const streetBytes = Buffer.from(addressInfo.street, "utf-8"); + const streetPadded = Buffer.alloc(16); + streetBytes.copy(streetPadded, 0, 0, Math.min(streetBytes.length, 16)); + data.push(...streetPadded); - // Add 1 byte padding at index 35 - data.push(0); + // Add 1 byte padding at index 35 + data.push(0); - // Pad city to 16 bytes (data[36..52]) - const cityBytes = Buffer.from(addressInfo.city, "utf-8"); - const cityPadded = Buffer.alloc(16); - cityBytes.copy(cityPadded, 0, 0, Math.min(cityBytes.length, 16)); - data.push(...cityPadded); + // Pad city to 16 bytes (data[36..52]) + const cityBytes = Buffer.from(addressInfo.city, "utf-8"); + const cityPadded = Buffer.alloc(16); + cityBytes.copy(cityPadded, 0, 0, Math.min(cityBytes.length, 16)); + data.push(...cityPadded); - return Buffer.from(data); + return Buffer.from(data); } function fromBytes(buffer: Buffer): AddressInfo { - // name: bytes 0..16 - const nameBytes = buffer.subarray(0, 16); - const name = nameBytes.toString("utf-8").replace(/\0/g, ""); + // name: bytes 0..16 + const nameBytes = buffer.subarray(0, 16); + const name = nameBytes.toString("utf-8").replace(/\0/g, ""); - // house_number: byte 17 - const house_number = buffer[17]; + // house_number: byte 17 + const house_number = buffer[17]; - // street: bytes 18..34 - const streetBytes = buffer.subarray(18, 34); - const street = streetBytes.toString("utf-8").replace(/\0/g, ""); + // street: bytes 18..34 + const streetBytes = buffer.subarray(18, 34); + const street = streetBytes.toString("utf-8").replace(/\0/g, ""); - // city: bytes 35..51 - const cityBytes = buffer.subarray(35, 51); - const city = cityBytes.toString("utf-8").replace(/\0/g, ""); + // city: bytes 35..51 + const cityBytes = buffer.subarray(35, 51); + const city = cityBytes.toString("utf-8").replace(/\0/g, ""); - return { name, house_number, street, city }; + return { name, house_number, street, city }; } describe("Account Data!", () => { - // Load the program keypair - const programKeypairPath = new URL( - "./fixtures/account_data_pinocchio_program-keypair.json", - // @ts-ignore - import.meta.url, - ).pathname; - const programKeypairData = JSON.parse(readFileSync(programKeypairPath, "utf-8")); - const programKeypair = Keypair.fromSecretKey(new Uint8Array(programKeypairData)); - const PROGRAM_ID = programKeypair.publicKey; - - // Load the program - const programPath = new URL( - "./fixtures/account_data_pinocchio_program.so", - // @ts-ignore - import.meta.url, - ).pathname; - - const litesvm = new LiteSVM(); - litesvm.addProgramFromFile(PROGRAM_ID, programPath); - - const payer = Keypair.generate(); - litesvm.airdrop(payer.publicKey, BigInt(100 * LAMPORTS_PER_SOL)); - - const addressInfoAccount = Keypair.generate(); - - test("Create the address info account", () => { - console.log(`Program Address : ${PROGRAM_ID}`); - console.log(`Payer Address : ${payer.publicKey}`); - console.log(`Address Info Acct : ${addressInfoAccount.publicKey}`); - - const addressInfo: AddressInfo = { - name: "Joe C", - house_number: 136, - street: "Mile High Dr.", - city: "Solana Beach", - }; - - const ix = new TransactionInstruction({ - keys: [ - { - pubkey: addressInfoAccount.publicKey, - isSigner: true, - isWritable: true, - }, - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId: PROGRAM_ID, - data: toBytes(addressInfo), - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = litesvm.latestBlockhash(); - tx.sign(payer, addressInfoAccount); - - litesvm.sendTransaction(tx); - }); - - test("Read the new account's data", () => { - const accountInfo = litesvm.getAccount(addressInfoAccount.publicKey); - - if (!accountInfo) { - throw new Error("Account not found"); - } - - const readAddressInfo = fromBytes(Buffer.from(accountInfo.data)); - - console.log(`Name : ${readAddressInfo.name}`); - console.log(`House Num: ${readAddressInfo.house_number}`); - console.log(`Street : ${readAddressInfo.street}`); - console.log(`City : ${readAddressInfo.city}`); - }); + // Load the program keypair + const programKeypairPath = new URL( + "./fixtures/account_data_pinocchio_program-keypair.json", + // @ts-expect-error + import.meta.url, + ).pathname; + const programKeypairData = JSON.parse(readFileSync(programKeypairPath, "utf-8")); + const programKeypair = Keypair.fromSecretKey(new Uint8Array(programKeypairData)); + const PROGRAM_ID = programKeypair.publicKey; + + // Load the program + const programPath = new URL( + "./fixtures/account_data_pinocchio_program.so", + // @ts-expect-error + import.meta.url, + ).pathname; + + const litesvm = new LiteSVM(); + litesvm.addProgramFromFile(PROGRAM_ID, programPath); + + const payer = Keypair.generate(); + litesvm.airdrop(payer.publicKey, BigInt(100 * LAMPORTS_PER_SOL)); + + const addressInfoAccount = Keypair.generate(); + + test("Create the address info account", () => { + console.log(`Program Address : ${PROGRAM_ID}`); + console.log(`Payer Address : ${payer.publicKey}`); + console.log(`Address Info Acct : ${addressInfoAccount.publicKey}`); + + const addressInfo: AddressInfo = { + name: "Joe C", + house_number: 136, + street: "Mile High Dr.", + city: "Solana Beach", + }; + + const ix = new TransactionInstruction({ + keys: [ + { + pubkey: addressInfoAccount.publicKey, + isSigner: true, + isWritable: true, + }, + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId: PROGRAM_ID, + data: toBytes(addressInfo), + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = litesvm.latestBlockhash(); + tx.sign(payer, addressInfoAccount); + + litesvm.sendTransaction(tx); + }); + + test("Read the new account's data", () => { + const accountInfo = litesvm.getAccount(addressInfoAccount.publicKey); + + if (!accountInfo) { + throw new Error("Account not found"); + } + + const readAddressInfo = fromBytes(Buffer.from(accountInfo.data)); + + console.log(`Name : ${readAddressInfo.name}`); + console.log(`House Num: ${readAddressInfo.house_number}`); + console.log(`Street : ${readAddressInfo.street}`); + console.log(`City : ${readAddressInfo.city}`); + }); }); - diff --git a/basics/checking-accounts/anchor/Anchor.toml b/basics/checking-accounts/anchor/Anchor.toml index cc8f9ed12..39bc5ddd9 100644 --- a/basics/checking-accounts/anchor/Anchor.toml +++ b/basics/checking-accounts/anchor/Anchor.toml @@ -2,15 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false -[programs.localnet] -checking_account_program = "ECWPhR3rJbaPfyNFgphnjxSEexbTArc7vxD8fnW6tgKw" +resolution = true +skip-lint = false -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +checking_account_program = "B56s2CGHWSG9HzzyYS5USQNYPJsB2teiUSKgG5CKpr2o" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/checking-accounts/anchor/package.json b/basics/checking-accounts/anchor/package.json index 31ba94982..a2f52fb80 100644 --- a/basics/checking-accounts/anchor/package.json +++ b/basics/checking-accounts/anchor/package.json @@ -1,18 +1,18 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/checking-accounts/anchor/pnpm-lock.yaml b/basics/checking-accounts/anchor/pnpm-lock.yaml index d0feff1e4..e6ecdc446 100644 --- a/basics/checking-accounts/anchor/pnpm-lock.yaml +++ b/basics/checking-accounts/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -45,18 +45,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': @@ -768,16 +768,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -795,7 +795,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: diff --git a/basics/checking-accounts/anchor/programs/anchor-program-example/Cargo.toml b/basics/checking-accounts/anchor/programs/anchor-program-example/Cargo.toml index a38a4ffcd..c02b5a14f 100644 --- a/basics/checking-accounts/anchor/programs/anchor-program-example/Cargo.toml +++ b/basics/checking-accounts/anchor/programs/anchor-program-example/Cargo.toml @@ -20,8 +20,14 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/checking-accounts/anchor/programs/anchor-program-example/src/lib.rs b/basics/checking-accounts/anchor/programs/anchor-program-example/src/lib.rs index 7eb51baa7..1b5edb40e 100644 --- a/basics/checking-accounts/anchor/programs/anchor-program-example/src/lib.rs +++ b/basics/checking-accounts/anchor/programs/anchor-program-example/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("ECWPhR3rJbaPfyNFgphnjxSEexbTArc7vxD8fnW6tgKw"); +declare_id!("B56s2CGHWSG9HzzyYS5USQNYPJsB2teiUSKgG5CKpr2o"); #[program] pub mod checking_account_program { diff --git a/basics/checking-accounts/anchor/programs/anchor-program-example/tests/test_checking_accounts.rs b/basics/checking-accounts/anchor/programs/anchor-program-example/tests/test_checking_accounts.rs new file mode 100644 index 000000000..33de2b6b8 --- /dev/null +++ b/basics/checking-accounts/anchor/programs/anchor-program-example/tests/test_checking_accounts.rs @@ -0,0 +1,61 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, system_instruction, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +#[test] +fn test_check_accounts() { + let program_id = checking_account_program::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/checking_account_program.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let account_to_change = Keypair::new(); + let account_to_create = Keypair::new(); + + // First, create an account owned by our program (like the TS test does) + let rent_exempt_balance = svm.minimum_balance_for_rent_exemption(0); + let create_account_ix = system_instruction::create_account( + &payer.pubkey(), + &account_to_change.pubkey(), + rent_exempt_balance, + 0, + &program_id, + ); + send_transaction_from_instructions( + &mut svm, + vec![create_account_ix], + &[&payer, &account_to_change], + &payer.pubkey(), + ) + .unwrap(); + + svm.expire_blockhash(); + + // Now call check_accounts + let check_accounts_ix = Instruction::new_with_bytes( + program_id, + &checking_account_program::instruction::CheckAccounts {}.data(), + checking_account_program::accounts::CheckingAccounts { + payer: payer.pubkey(), + account_to_create: account_to_create.pubkey(), + account_to_change: account_to_change.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![check_accounts_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); +} diff --git a/basics/checking-accounts/anchor/tests/bankrun.test.ts b/basics/checking-accounts/anchor/tests/bankrun.test.ts index d47712601..cb9839edf 100644 --- a/basics/checking-accounts/anchor/tests/bankrun.test.ts +++ b/basics/checking-accounts/anchor/tests/bankrun.test.ts @@ -1,63 +1,52 @@ import { describe, it } from "node:test"; import * as anchor from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction } from "@solana/web3.js"; import { BankrunProvider } from "anchor-bankrun"; import { startAnchor } from "solana-bankrun"; +import IDL from "../target/idl/checking_account_program.json" with { type: "json" }; import type { CheckingAccountProgram } from "../target/types/checking_account_program"; -import IDL from "../target/idl/checking_account_program.json" with { - type: "json", -}; const PROGRAM_ID = new PublicKey(IDL.address); describe("Bankrun example", async () => { - const context = await startAnchor( - "", - [{ name: "checking_account_program", programId: PROGRAM_ID }], - [], - ); - const provider = new BankrunProvider(context); - - const wallet = provider.wallet as anchor.Wallet; - const program = new anchor.Program(IDL, provider); - const client = context.banksClient; - - // We'll create this ahead of time. - // Our program will try to modify it. - const accountToChange = new Keypair(); - // Our program will create this. - const accountToCreate = new Keypair(); - - it("Create an account owned by our program", async () => { - const instruction = SystemProgram.createAccount({ - fromPubkey: provider.wallet.publicKey, - newAccountPubkey: accountToChange.publicKey, - lamports: await provider.connection.getMinimumBalanceForRentExemption(0), - space: 0, - programId: program.programId, // Our program - }); - - const transaction = new Transaction(); - const blockhash = context.lastBlockhash; - - transaction.recentBlockhash = blockhash; - transaction.add(instruction).sign(wallet.payer, accountToChange); - await client.processTransaction(transaction); - }); - - it("Check accounts", async () => { - await program.methods - .checkAccounts() - .accounts({ - payer: wallet.publicKey, - accountToCreate: accountToCreate.publicKey, - accountToChange: accountToChange.publicKey, - }) - .rpc(); - }); + const context = await startAnchor("", [{ name: "checking_account_program", programId: PROGRAM_ID }], []); + const provider = new BankrunProvider(context); + + const wallet = provider.wallet as anchor.Wallet; + const program = new anchor.Program(IDL, provider); + const client = context.banksClient; + + // We'll create this ahead of time. + // Our program will try to modify it. + const accountToChange = new Keypair(); + // Our program will create this. + const accountToCreate = new Keypair(); + + it("Create an account owned by our program", async () => { + const instruction = SystemProgram.createAccount({ + fromPubkey: provider.wallet.publicKey, + newAccountPubkey: accountToChange.publicKey, + lamports: await provider.connection.getMinimumBalanceForRentExemption(0), + space: 0, + programId: program.programId, // Our program + }); + + const transaction = new Transaction(); + const blockhash = context.lastBlockhash; + + transaction.recentBlockhash = blockhash; + transaction.add(instruction).sign(wallet.payer, accountToChange); + await client.processTransaction(transaction); + }); + + it("Check accounts", async () => { + await program.methods + .checkAccounts() + .accounts({ + payer: wallet.publicKey, + accountToCreate: accountToCreate.publicKey, + accountToChange: accountToChange.publicKey, + }) + .rpc(); + }); }); diff --git a/basics/checking-accounts/anchor/tests/test.ts b/basics/checking-accounts/anchor/tests/test.ts index 9b5599e18..514bca172 100644 --- a/basics/checking-accounts/anchor/tests/test.ts +++ b/basics/checking-accounts/anchor/tests/test.ts @@ -1,50 +1,41 @@ import * as anchor from "@anchor-lang/core"; -import { - Keypair, - SystemProgram, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; +import { Keypair, SystemProgram, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; import type { CheckingAccountProgram } from "../target/types/checking_account_program"; describe("Anchor example", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const program = anchor.workspace - .CheckingAccountProgram as anchor.Program; - const wallet = provider.wallet as anchor.Wallet; + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const program = anchor.workspace.CheckingAccountProgram as anchor.Program; + const wallet = provider.wallet as anchor.Wallet; - // We'll create this ahead of time. - // Our program will try to modify it. - const accountToChange = new Keypair(); - // Our program will create this. - const accountToCreate = new Keypair(); + // We'll create this ahead of time. + // Our program will try to modify it. + const accountToChange = new Keypair(); + // Our program will create this. + const accountToCreate = new Keypair(); - it("Create an account owned by our program", async () => { - const instruction = SystemProgram.createAccount({ - fromPubkey: provider.wallet.publicKey, - newAccountPubkey: accountToChange.publicKey, - lamports: await provider.connection.getMinimumBalanceForRentExemption(0), - space: 0, - programId: program.programId, // Our program - }); + it("Create an account owned by our program", async () => { + const instruction = SystemProgram.createAccount({ + fromPubkey: provider.wallet.publicKey, + newAccountPubkey: accountToChange.publicKey, + lamports: await provider.connection.getMinimumBalanceForRentExemption(0), + space: 0, + programId: program.programId, // Our program + }); - const transaction = new Transaction().add(instruction); + const transaction = new Transaction().add(instruction); - await sendAndConfirmTransaction(provider.connection, transaction, [ - wallet.payer, - accountToChange, - ]); - }); + await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer, accountToChange]); + }); - it("Check accounts", async () => { - await program.methods - .checkAccounts() - .accounts({ - payer: wallet.publicKey, - accountToCreate: accountToCreate.publicKey, - accountToChange: accountToChange.publicKey, - }) - .rpc(); - }); + it("Check accounts", async () => { + await program.methods + .checkAccounts() + .accounts({ + payer: wallet.publicKey, + accountToCreate: accountToCreate.publicKey, + accountToChange: accountToChange.publicKey, + }) + .rpc(); + }); }); diff --git a/basics/checking-accounts/native/program/Cargo.toml b/basics/checking-accounts/native/program/Cargo.toml index 214ea7856..4ee029de8 100644 --- a/basics/checking-accounts/native/program/Cargo.toml +++ b/basics/checking-accounts/native/program/Cargo.toml @@ -19,7 +19,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" solana-pubkey = "3.0.0" diff --git a/basics/checking-accounts/native/tests/test.ts b/basics/checking-accounts/native/tests/test.ts index 8e39eea31..a64bd5e0b 100644 --- a/basics/checking-accounts/native/tests/test.ts +++ b/basics/checking-accounts/native/tests/test.ts @@ -1,10 +1,10 @@ -import { describe, test } from 'node:test'; -import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js'; -import { start } from 'solana-bankrun'; +import { describe, test } from "node:test"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; +import { start } from "solana-bankrun"; -describe('Checking accounts', async () => { +describe("Checking accounts", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'checking_accounts_native_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "checking_accounts_native_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; const rent = await client.getRent(); @@ -15,7 +15,7 @@ describe('Checking accounts', async () => { // Our program will create this. const accountToCreate = Keypair.generate(); - test('Create an account owned by our program', async () => { + test("Create an account owned by our program", async () => { const blockhash = context.lastBlockhash; const ix = SystemProgram.createAccount({ fromPubkey: payer.publicKey, @@ -32,7 +32,7 @@ describe('Checking accounts', async () => { await client.processTransaction(tx); }); - test('Check accounts', async () => { + test("Check accounts", async () => { const blockhash = context.lastBlockhash; const ix = new TransactionInstruction({ keys: [ diff --git a/basics/checking-accounts/pinocchio/program/Cargo.toml b/basics/checking-accounts/pinocchio/program/Cargo.toml index 5eebeb583..f03a6369b 100644 --- a/basics/checking-accounts/pinocchio/program/Cargo.toml +++ b/basics/checking-accounts/pinocchio/program/Cargo.toml @@ -9,7 +9,7 @@ pinocchio-system.workspace = true pinocchio-log.workspace = true [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" solana-pubkey = "3.0.0" diff --git a/basics/checking-accounts/pinocchio/tests/test.ts b/basics/checking-accounts/pinocchio/tests/test.ts index 7dcc9d8b5..ea6a1a548 100644 --- a/basics/checking-accounts/pinocchio/tests/test.ts +++ b/basics/checking-accounts/pinocchio/tests/test.ts @@ -1,19 +1,10 @@ import { describe, test } from "node:test"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; import { start } from "solana-bankrun"; describe("Checking accounts", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start( - [{ name: "checking_accounts_pinocchio_program", programId: PROGRAM_ID }], - [], - ); + const context = await start([{ name: "checking_accounts_pinocchio_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; const rent = await client.getRent(); diff --git a/basics/close-account/anchor/Anchor.toml b/basics/close-account/anchor/Anchor.toml index abe70b718..77fdf792d 100644 --- a/basics/close-account/anchor/Anchor.toml +++ b/basics/close-account/anchor/Anchor.toml @@ -2,17 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false [programs.localnet] -close_account_program = "99TQtoDdQ5NS2v5Ppha93aqEmv3vV9VZVfHTP5rGST3c" - -# [registry] section removed — no longer used in Anchor 1.0 +close_account_program = "E7Cgyech7DrHz39ctmsPe6xqe65YJKWg1jwQQpmZrtcm" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/close-account/anchor/migrations/deploy.ts b/basics/close-account/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/basics/close-account/anchor/migrations/deploy.ts +++ b/basics/close-account/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/basics/close-account/anchor/package.json b/basics/close-account/anchor/package.json index 0955a189f..e09b39ceb 100644 --- a/basics/close-account/anchor/package.json +++ b/basics/close-account/anchor/package.json @@ -1,23 +1,23 @@ { - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - }, - "type": "module" + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + }, + "type": "module" } diff --git a/basics/close-account/anchor/pnpm-lock.yaml b/basics/close-account/anchor/pnpm-lock.yaml index 6d5cf4fb1..4e677c70a 100644 --- a/basics/close-account/anchor/pnpm-lock.yaml +++ b/basics/close-account/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -48,18 +48,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': @@ -821,16 +821,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -848,7 +848,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: diff --git a/basics/close-account/anchor/programs/close-account/Cargo.toml b/basics/close-account/anchor/programs/close-account/Cargo.toml index 6a257d0ce..477a8700b 100644 --- a/basics/close-account/anchor/programs/close-account/Cargo.toml +++ b/basics/close-account/anchor/programs/close-account/Cargo.toml @@ -20,8 +20,13 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/close-account/anchor/programs/close-account/src/lib.rs b/basics/close-account/anchor/programs/close-account/src/lib.rs index fd298e7bd..61d7f4f10 100644 --- a/basics/close-account/anchor/programs/close-account/src/lib.rs +++ b/basics/close-account/anchor/programs/close-account/src/lib.rs @@ -3,7 +3,7 @@ mod instructions; mod state; use instructions::*; -declare_id!("99TQtoDdQ5NS2v5Ppha93aqEmv3vV9VZVfHTP5rGST3c"); +declare_id!("E7Cgyech7DrHz39ctmsPe6xqe65YJKWg1jwQQpmZrtcm"); #[program] pub mod close_account_program { diff --git a/basics/close-account/anchor/programs/close-account/tests/test_close_account.rs b/basics/close-account/anchor/programs/close-account/tests/test_close_account.rs new file mode 100644 index 000000000..cbc2952d6 --- /dev/null +++ b/basics/close-account/anchor/programs/close-account/tests/test_close_account.rs @@ -0,0 +1,71 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Keypair) { + let program_id = close_account_program::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/close_account_program.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, payer) +} + +#[test] +fn test_create_and_close_user() { + let (mut svm, payer) = setup(); + let program_id = close_account_program::id(); + + // Derive the PDA for the user's account + let (user_account_pda, _bump) = + Pubkey::find_program_address(&[b"USER", payer.pubkey().as_ref()], &program_id); + + // Create user + let create_ix = Instruction::new_with_bytes( + program_id, + &close_account_program::instruction::CreateUser { + name: "John Doe".to_string(), + } + .data(), + close_account_program::accounts::CreateUserContext { + user: payer.pubkey(), + user_account: user_account_pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![create_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + // Verify account exists and has correct data + let account = svm + .get_account(&user_account_pda) + .expect("Account should exist after creation"); + assert!(account.data.len() > 0, "Account should have data"); + + svm.expire_blockhash(); + + // Close user + let close_ix = Instruction::new_with_bytes( + program_id, + &close_account_program::instruction::CloseUser {}.data(), + close_account_program::accounts::CloseUserContext { + user: payer.pubkey(), + user_account: user_account_pda, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![close_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + // Verify account is closed + let account = svm.get_account(&user_account_pda); + assert!(account.is_none(), "Account should be closed"); +} diff --git a/basics/close-account/anchor/tests/litesvm.test.ts b/basics/close-account/anchor/tests/litesvm.test.ts index 5dead96f1..304620d54 100644 --- a/basics/close-account/anchor/tests/litesvm.test.ts +++ b/basics/close-account/anchor/tests/litesvm.test.ts @@ -1,101 +1,93 @@ import anchor from "@anchor-lang/core"; import { - Keypair, - LAMPORTS_PER_SOL, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, + Keypair, + LAMPORTS_PER_SOL, + PublicKey, + SystemProgram, + Transaction, + TransactionInstruction, } from "@solana/web3.js"; import { assert } from "chai"; import { LiteSVM } from "litesvm"; -import IDL from "../target/idl/close_account_program.json" with { - type: "json", -}; +import IDL from "../target/idl/close_account_program.json" with { type: "json" }; describe("LiteSVM: Close an account", () => { - const litesvm = new LiteSVM(); - const programId = new PublicKey(IDL.address); - const payer = Keypair.generate(); - const coder = new anchor.BorshCoder(IDL as anchor.Idl); // For serialization and deserialization + const litesvm = new LiteSVM(); + const programId = new PublicKey(IDL.address); + const payer = Keypair.generate(); + const coder = new anchor.BorshCoder(IDL as anchor.Idl); // For serialization and deserialization - const programPath = new URL( - "../target/deploy/close_account_program.so", - import.meta.url, - ).pathname; - litesvm.addProgramFromFile(programId, programPath); + const programPath = new URL("../target/deploy/close_account_program.so", import.meta.url).pathname; + litesvm.addProgramFromFile(programId, programPath); - litesvm.airdrop(payer.publicKey, BigInt(5 * LAMPORTS_PER_SOL)); + litesvm.airdrop(payer.publicKey, BigInt(5 * LAMPORTS_PER_SOL)); - /** - * Derive the PDA for the user's account. - */ - const [userAccountAddress] = PublicKey.findProgramAddressSync( - [Buffer.from("USER"), payer.publicKey.toBuffer()], - programId, - ); + /** + * Derive the PDA for the user's account. + */ + const [userAccountAddress] = PublicKey.findProgramAddressSync( + [Buffer.from("USER"), payer.publicKey.toBuffer()], + programId, + ); - it("Create an account", () => { - /** - * Instruction data - * Convert into buffer of instruction data - */ - const dataArg = { name: "John Doe" }; - const data = coder.instruction.encode("create_user", dataArg); + it("Create an account", () => { + /** + * Instruction data + * Convert into buffer of instruction data + */ + const dataArg = { name: "John Doe" }; + const data = coder.instruction.encode("create_user", dataArg); - /** - * Create Transactions - */ - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: userAccountAddress, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); + /** + * Create Transactions + */ + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: userAccountAddress, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = litesvm.latestBlockhash(); - tx.sign(payer); - litesvm.sendTransaction(tx); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = litesvm.latestBlockhash(); + tx.sign(payer); + litesvm.sendTransaction(tx); - /** - * Fetch account - */ - const userAccount = litesvm.getAccount(userAccountAddress); - const user = coder.accounts.decode( - "UserState", - Buffer.from(userAccount.data), - ); - assert.equal(user.name, "John Doe"); - assert.equal(user.user.toBase58(), payer.publicKey.toBase58()); - }); + /** + * Fetch account + */ + const userAccount = litesvm.getAccount(userAccountAddress); + const user = coder.accounts.decode("UserState", Buffer.from(userAccount.data)); + assert.equal(user.name, "John Doe"); + assert.equal(user.user.toBase58(), payer.publicKey.toBase58()); + }); - it("Close an account", () => { - const data = coder.instruction.encode("close_user", {}); + it("Close an account", () => { + const data = coder.instruction.encode("close_user", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: userAccountAddress, isSigner: false, isWritable: true }, - ], - programId, - data, - }); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: userAccountAddress, isSigner: false, isWritable: true }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = litesvm.latestBlockhash(); - tx.sign(payer); - litesvm.sendTransaction(tx); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = litesvm.latestBlockhash(); + tx.sign(payer); + litesvm.sendTransaction(tx); - /** - * Fetch account - */ - const userAccount = litesvm.getAccount(userAccountAddress); - assert.equal(userAccount, null); - }); + /** + * Fetch account + */ + const userAccount = litesvm.getAccount(userAccountAddress); + assert.equal(userAccount, null); + }); }); diff --git a/basics/close-account/anchor/tests/test.ts b/basics/close-account/anchor/tests/test.ts index 4623c0d19..988ebd5f5 100644 --- a/basics/close-account/anchor/tests/test.ts +++ b/basics/close-account/anchor/tests/test.ts @@ -5,57 +5,54 @@ import { assert } from "chai"; import type { CloseAccountProgram } from "../target/types/close_account_program.ts"; describe("Anchor: Close an account", () => { - /** - * Configure the client to use the local cluster. - */ - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); + /** + * Configure the client to use the local cluster. + */ + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); - const program = anchor.workspace - .CloseAccountProgram as Program; - const payer = provider.wallet as anchor.Wallet; + const program = anchor.workspace.CloseAccountProgram as Program; + const payer = provider.wallet as anchor.Wallet; - /** - * Derive the PDA for the user's account. - */ - const [userAccountAddress] = PublicKey.findProgramAddressSync( - [Buffer.from("USER"), payer.publicKey.toBuffer()], - program.programId, - ); + /** + * Derive the PDA for the user's account. + */ + const [userAccountAddress] = PublicKey.findProgramAddressSync( + [Buffer.from("USER"), payer.publicKey.toBuffer()], + program.programId, + ); - it("Create an account", async () => { - await program.methods - .createUser("John Doe") - .accounts({ - user: payer.publicKey, - userAccount: userAccountAddress, - system_program: SystemProgram.programId, - }) - .rpc(); + it("Create an account", async () => { + await program.methods + .createUser("John Doe") + .accounts({ + user: payer.publicKey, + userAccount: userAccountAddress, + system_program: SystemProgram.programId, + }) + .rpc(); - /** - * Fetch account - */ - const userAccount = - await program.account.userState.fetch(userAccountAddress); - assert.equal(userAccount.name, "John Doe"); - assert.equal(userAccount.user.toBase58(), payer.publicKey.toBase58()); - }); + /** + * Fetch account + */ + const userAccount = await program.account.userState.fetch(userAccountAddress); + assert.equal(userAccount.name, "John Doe"); + assert.equal(userAccount.user.toBase58(), payer.publicKey.toBase58()); + }); - it("Close an account", async () => { - await program.methods - .closeUser() - .accounts({ - user: payer.publicKey, - userAccount: userAccountAddress, - }) - .rpc(); + it("Close an account", async () => { + await program.methods + .closeUser() + .accounts({ + user: payer.publicKey, + userAccount: userAccountAddress, + }) + .rpc(); - /** - * Fetch account - */ - const userAccount = - await program.account.userState.fetchNullable(userAccountAddress); - assert.equal(userAccount, null); - }); + /** + * Fetch account + */ + const userAccount = await program.account.userState.fetchNullable(userAccountAddress); + assert.equal(userAccount, null); + }); }); diff --git a/basics/close-account/anchor/tsconfig.json b/basics/close-account/anchor/tsconfig.json index 88e8865f0..ce454c83b 100644 --- a/basics/close-account/anchor/tsconfig.json +++ b/basics/close-account/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "typeRoots": ["./node_modules/@types"], - "lib": ["es2020"], - "module": "nodenext", - "target": "es2020", - "esModuleInterop": true, - "resolveJsonModule": true - } + "compilerOptions": { + "typeRoots": ["./node_modules/@types"], + "lib": ["es2020"], + "module": "nodenext", + "target": "es2020", + "esModuleInterop": true, + "resolveJsonModule": true + } } diff --git a/basics/close-account/native/program/Cargo.toml b/basics/close-account/native/program/Cargo.toml index 5bedf0754..ca3d566e6 100644 --- a/basics/close-account/native/program/Cargo.toml +++ b/basics/close-account/native/program/Cargo.toml @@ -20,7 +20,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/close-account/native/tests/close-account.test.ts b/basics/close-account/native/tests/close-account.test.ts index cb8640c3d..df253f1fb 100644 --- a/basics/close-account/native/tests/close-account.test.ts +++ b/basics/close-account/native/tests/close-account.test.ts @@ -1,19 +1,22 @@ -import { describe, test } from 'node:test'; -import { PublicKey, Transaction } from '@solana/web3.js'; -import { start } from 'solana-bankrun'; -import { createCloseUserInstruction, createCreateUserInstruction } from '../ts'; +import { describe, test } from "node:test"; +import { PublicKey, Transaction } from "@solana/web3.js"; +import { start } from "solana-bankrun"; +import { createCloseUserInstruction, createCreateUserInstruction } from "../ts"; -describe('Close Account!', async () => { +describe("Close Account!", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'close_account_native_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "close_account_native_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; - const testAccountPublicKey = PublicKey.findProgramAddressSync([Buffer.from('USER'), payer.publicKey.toBuffer()], PROGRAM_ID)[0]; + const testAccountPublicKey = PublicKey.findProgramAddressSync( + [Buffer.from("USER"), payer.publicKey.toBuffer()], + PROGRAM_ID, + )[0]; - test('Create the account', async () => { + test("Create the account", async () => { const blockhash = context.lastBlockhash; - const ix = createCreateUserInstruction(testAccountPublicKey, payer.publicKey, PROGRAM_ID, 'Jacob'); + const ix = createCreateUserInstruction(testAccountPublicKey, payer.publicKey, PROGRAM_ID, "Jacob"); const tx = new Transaction(); tx.recentBlockhash = blockhash; @@ -22,7 +25,7 @@ describe('Close Account!', async () => { await client.processTransaction(tx); }); - test('Close the account', async () => { + test("Close the account", async () => { const blockhash = context.lastBlockhash; const ix = createCloseUserInstruction(testAccountPublicKey, payer.publicKey, PROGRAM_ID); diff --git a/basics/close-account/native/ts/index.ts b/basics/close-account/native/ts/index.ts index 898deed08..110032b71 100644 --- a/basics/close-account/native/ts/index.ts +++ b/basics/close-account/native/ts/index.ts @@ -1,2 +1,2 @@ -export * from './instructions'; -export * from './state'; +export * from "./instructions"; +export * from "./state"; diff --git a/basics/close-account/native/ts/instructions/close.ts b/basics/close-account/native/ts/instructions/close.ts index 697d347bf..3bc4afd37 100644 --- a/basics/close-account/native/ts/instructions/close.ts +++ b/basics/close-account/native/ts/instructions/close.ts @@ -1,7 +1,7 @@ -import { Buffer } from 'node:buffer'; -import { type PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { MyInstruction } from '.'; +import { Buffer } from "node:buffer"; +import { type PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { MyInstruction } from "."; export class Close { instruction: MyInstruction; @@ -25,13 +25,17 @@ export const CloseSchema = new Map([ [ Close, { - kind: 'struct', - fields: [['instruction', 'u8']], + kind: "struct", + fields: [["instruction", "u8"]], }, ], ]); -export function createCloseUserInstruction(target: PublicKey, payer: PublicKey, programId: PublicKey): TransactionInstruction { +export function createCloseUserInstruction( + target: PublicKey, + payer: PublicKey, + programId: PublicKey, +): TransactionInstruction { const instructionObject = new Close({ instruction: MyInstruction.CloseUser, }); diff --git a/basics/close-account/native/ts/instructions/create.ts b/basics/close-account/native/ts/instructions/create.ts index 100b6cd68..7a18c43ac 100644 --- a/basics/close-account/native/ts/instructions/create.ts +++ b/basics/close-account/native/ts/instructions/create.ts @@ -1,7 +1,7 @@ -import { Buffer } from 'node:buffer'; -import { type PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { MyInstruction } from '.'; +import { Buffer } from "node:buffer"; +import { type PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { MyInstruction } from "."; export class Create { instruction: MyInstruction; @@ -25,16 +25,21 @@ export const CreateSchema = new Map([ [ Create, { - kind: 'struct', + kind: "struct", fields: [ - ['instruction', 'u8'], - ['name', 'string'], + ["instruction", "u8"], + ["name", "string"], ], }, ], ]); -export function createCreateUserInstruction(target: PublicKey, payer: PublicKey, programId: PublicKey, name: string): TransactionInstruction { +export function createCreateUserInstruction( + target: PublicKey, + payer: PublicKey, + programId: PublicKey, + name: string, +): TransactionInstruction { const instructionObject = new Create({ instruction: MyInstruction.CreateUser, name, diff --git a/basics/close-account/native/ts/state/index.ts b/basics/close-account/native/ts/state/index.ts index 4dad1be41..440a115d4 100644 --- a/basics/close-account/native/ts/state/index.ts +++ b/basics/close-account/native/ts/state/index.ts @@ -1,5 +1,5 @@ -import { Buffer } from 'node:buffer'; -import * as borsh from 'borsh'; +import { Buffer } from "node:buffer"; +import * as borsh from "borsh"; export class User { name: string; @@ -27,8 +27,8 @@ export const UserSchema = new Map([ [ User, { - kind: 'struct', - fields: [['name', 'string']], + kind: "struct", + fields: [["name", "string"]], }, ], ]); diff --git a/basics/close-account/pinocchio/program/Cargo.toml b/basics/close-account/pinocchio/program/Cargo.toml index e1c7f3307..3c6d7e48f 100644 --- a/basics/close-account/pinocchio/program/Cargo.toml +++ b/basics/close-account/pinocchio/program/Cargo.toml @@ -10,7 +10,7 @@ pinocchio-pubkey.workspace = true pinocchio-system.workspace = true [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-keypair = "3.0.1" solana-message = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/close-account/pinocchio/tests/close-account.test.ts b/basics/close-account/pinocchio/tests/close-account.test.ts index e073c28c7..163818817 100644 --- a/basics/close-account/pinocchio/tests/close-account.test.ts +++ b/basics/close-account/pinocchio/tests/close-account.test.ts @@ -1,6 +1,4 @@ -import { describe, test } from "node:test"; -import { PublicKey, Transaction } from "@solana/web3.js"; -import { start } from "solana-bankrun"; +import { describe } from "node:test"; describe("Close Account!", async () => { console.log("Close Account"); diff --git a/basics/counter/anchor/Anchor.toml b/basics/counter/anchor/Anchor.toml index a07cc9353..e5803a783 100644 --- a/basics/counter/anchor/Anchor.toml +++ b/basics/counter/anchor/Anchor.toml @@ -2,17 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false [programs.localnet] -counter_anchor = "BmDHboaj1kBUoinJKKSRqKfMeRKJqQqEbUj1VgzeQe4A" - -# [registry] section removed — no longer used in Anchor 1.0 +counter_anchor = "9nG25nFpLsycMERePF627oKHm5cHvNyv2TbfiFck32EP" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/counter/anchor/migrations/deploy.ts b/basics/counter/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/basics/counter/anchor/migrations/deploy.ts +++ b/basics/counter/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/basics/counter/anchor/package.json b/basics/counter/anchor/package.json deleted file mode 100644 index 21d106e4d..000000000 --- a/basics/counter/anchor/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - }, - "type": "module" -} diff --git a/basics/counter/anchor/pnpm-lock.yaml b/basics/counter/anchor/pnpm-lock.yaml deleted file mode 100644 index ca3afd7ff..000000000 --- a/basics/counter/anchor/pnpm-lock.yaml +++ /dev/null @@ -1,1476 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/web3.js': - specifier: ^1.98.4 - version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - litesvm: - specifier: ^0.4.0 - version: 0.4.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - devDependencies: - '@types/bn.js': - specifier: ^5.1.0 - version: 5.1.5 - '@types/chai': - specifier: ^4.3.0 - version: 4.3.16 - '@types/mocha': - specifier: ^9.0.0 - version: 9.1.1 - chai: - specifier: ^4.3.4 - version: 4.4.1 - mocha: - specifier: ^9.0.3 - version: 9.2.2 - prettier: - specifier: ^2.6.2 - version: 2.8.8 - ts-mocha: - specifier: ^10.0.0 - version: 10.0.0(mocha@9.2.2) - typescript: - specifier: ^5.3.3 - version: 5.9.3 - -packages: - - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} - engines: {node: '>=10'} - peerDependencies: - '@solana/web3.js': ^1.69.0 - - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} - engines: {node: '>=17'} - - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} - engines: {node: '>=10'} - - '@babel/runtime@7.25.0': - resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==} - engines: {node: '>=6.9.0'} - - '@noble/curves@1.4.2': - resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} - - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - - '@noble/hashes@1.8.0': - resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} - engines: {node: ^14.21.3 || >=16} - - '@solana/buffer-layout@4.0.1': - resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} - engines: {node: '>=5.10'} - - '@solana/codecs-core@2.3.0': - resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==} - engines: {node: '>=20.18.0'} - peerDependencies: - typescript: '>=5.3.3' - - '@solana/codecs-numbers@2.3.0': - resolution: {integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==} - engines: {node: '>=20.18.0'} - peerDependencies: - typescript: '>=5.3.3' - - '@solana/errors@2.3.0': - resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==} - engines: {node: '>=20.18.0'} - hasBin: true - peerDependencies: - typescript: '>=5.3.3' - - '@solana/web3.js@1.98.4': - resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==} - - '@swc/helpers@0.5.12': - resolution: {integrity: sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==} - - '@types/bn.js@5.1.5': - resolution: {integrity: sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==} - - '@types/chai@4.3.16': - resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} - - '@types/connect@3.4.38': - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - - '@types/mocha@9.1.1': - resolution: {integrity: sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==} - - '@types/node@12.20.55': - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - - '@types/node@20.12.11': - resolution: {integrity: sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==} - - '@types/uuid@8.3.4': - resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} - - '@types/ws@7.4.7': - resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} - - '@types/ws@8.5.12': - resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} - - '@ungap/promise-all-settled@1.1.2': - resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} - - JSONStream@1.3.5: - resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} - hasBin: true - - agentkeepalive@4.5.0: - resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} - engines: {node: '>= 8.0.0'} - - ansi-colors@4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} - engines: {node: '>=6'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base-x@3.0.9: - resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - bn.js@5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - - bn.js@5.2.2: - resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} - - borsh@0.7.0: - resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - - browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - - bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - buffer-layout@1.2.2: - resolution: {integrity: sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==} - engines: {node: '>=4.5'} - - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - bufferutil@4.0.8: - resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} - engines: {node: '>=6.14.2'} - - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chalk@5.6.2: - resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - - chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - commander@14.0.2: - resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} - engines: {node: '>=20'} - - commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - cross-fetch@3.2.0: - resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} - - debug@4.3.3: - resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - - deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} - - delay@5.0.0: - resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} - engines: {node: '>=10'} - - diff@3.5.0: - resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} - engines: {node: '>=0.3.1'} - - diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - es6-promise@4.2.8: - resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} - - es6-promisify@5.0.0: - resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - - eyes@0.1.8: - resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} - engines: {node: '> 0.1.90'} - - fast-stable-stringify@1.0.0: - resolution: {integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==} - - fastestsmallesttextencoderdecoder@1.0.22: - resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} - - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob@7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} - - growl@1.10.5: - resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==} - engines: {node: '>=4.x'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - isomorphic-ws@4.0.1: - resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} - peerDependencies: - ws: '*' - - jayson@4.1.1: - resolution: {integrity: sha512-5ZWm4Q/0DHPyeMfAsrwViwUS2DMVsQgWh8bEEIVTkfb3DzHZ2L3G5WUnF+AKmGjjM9r1uAv73SaqC1/U4RL45w==} - engines: {node: '>=8'} - hasBin: true - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - - json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - - jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - - litesvm-darwin-arm64@0.4.0: - resolution: {integrity: sha512-LN6iZcUQ6Xi5KO/7yJBYSALjjDCI/s/s2PgV3BqM4dpeBaLz+fXX/+qgMcBgpEVgEdEmhelux+WtAMkbEzJfrA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - litesvm-darwin-x64@0.4.0: - resolution: {integrity: sha512-3ltogKQdle8LbakVqoB6plxaNwp6Vb3tnkqa3G5mAvvZNorB2iumThDaTZ381Knl69t566LZm+g/VDZwYfsfhA==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] - - litesvm-linux-arm64-gnu@0.4.0: - resolution: {integrity: sha512-SWlcRUqkXCMgLoDX/Wqr/S1lff+ggVI9f0YrRJMraxtEyApxutAoW2AWw4tvo6DsEgNwjxgsZOAwnE6bQBv8CA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - litesvm-linux-arm64-musl@0.4.0: - resolution: {integrity: sha512-YMMqwEWJUSWwL0Rwp8dFwl3jvgNU21eI7Qc+BpH9u2yeIRYQTn3rNGDnsK8v3QIZPHQdMo7NrPhzk4XoB1aKPg==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [musl] - - litesvm-linux-x64-gnu@0.4.0: - resolution: {integrity: sha512-brZ3tFABDVQEYCgci7AO8iVYLw10UXVo97/lpTy75bTzNoqkggg8wFQOrbgCdb9NRwt06Y4Zf8cpIZAoDQq2mw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [glibc] - - litesvm-linux-x64-musl@0.4.0: - resolution: {integrity: sha512-D98qdIOuWg4fOewIIiH1D23AtM4I7/3vLKXIL8uQz06D5ev5fsBzNp2gM7libAywTkCYy/u666xgD6PsWhrTaw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [musl] - - litesvm@0.4.0: - resolution: {integrity: sha512-ySr5mB2ap4SzJpmVR2I5+gjzTH8NJbkg7DYPormzA2U9F4LhfvTTrD17X/k5N3Bn4b5Db6/CwSyX2qc0HrJtNA==} - engines: {node: '>= 20'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@4.2.1: - resolution: {integrity: sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==} - engines: {node: '>=10'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - mocha@9.2.2: - resolution: {integrity: sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==} - engines: {node: '>= 12.0.0'} - hasBin: true - - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.1: - resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - - node-gyp-build@4.8.1: - resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} - hasBin: true - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - pako@2.1.0: - resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - rpc-websockets@9.0.2: - resolution: {integrity: sha512-YzggvfItxMY3Lwuax5rC18inhbjJv9Py7JXRHxTIi94JOLrqBsSsUUc5bbl5W6c11tXhdfpDPK0KzBhoGe8jjw==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - serialize-javascript@6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} - - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - superstruct@0.15.5: - resolution: {integrity: sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==} - - superstruct@2.0.2: - resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} - engines: {node: '>=14.0.0'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - text-encoding-utf-8@1.0.2: - resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} - - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - toml@3.0.0: - resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} - - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - ts-mocha@10.0.0: - resolution: {integrity: sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw==} - engines: {node: '>= 6.X.X'} - hasBin: true - peerDependencies: - mocha: ^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X - - ts-node@7.0.1: - resolution: {integrity: sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==} - engines: {node: '>=4.2.0'} - hasBin: true - - tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - utf-8-validate@5.0.10: - resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} - engines: {node: '>=6.14.2'} - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - workerpool@6.2.0: - resolution: {integrity: sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yargs-parser@20.2.4: - resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} - engines: {node: '>=10'} - - yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} - - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - - yn@2.0.0: - resolution: {integrity: sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==} - engines: {node: '>=4'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': - dependencies: - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - bn.js: 5.2.2 - buffer-layout: 1.2.2 - - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 - '@noble/hashes': 1.8.0 - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - bn.js: 5.2.2 - bs58: 4.0.1 - buffer-layout: 1.2.2 - camelcase: 6.3.0 - cross-fetch: 3.2.0 - eventemitter3: 4.0.7 - pako: 2.1.0 - superstruct: 0.15.5 - toml: 3.0.0 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - '@anchor-lang/errors@1.0.0-rc.5': {} - - '@babel/runtime@7.25.0': - dependencies: - regenerator-runtime: 0.14.1 - - '@noble/curves@1.4.2': - dependencies: - '@noble/hashes': 1.4.0 - - '@noble/hashes@1.4.0': {} - - '@noble/hashes@1.8.0': {} - - '@solana/buffer-layout@4.0.1': - dependencies: - buffer: 6.0.3 - - '@solana/codecs-core@2.3.0(typescript@5.9.3)': - dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - - '@solana/codecs-numbers@2.3.0(typescript@5.9.3)': - dependencies: - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - - '@solana/errors@2.3.0(typescript@5.9.3)': - dependencies: - chalk: 5.6.2 - commander: 14.0.2 - typescript: 5.9.3 - - '@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@babel/runtime': 7.25.0 - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@solana/buffer-layout': 4.0.1 - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) - agentkeepalive: 4.5.0 - bn.js: 5.2.1 - borsh: 0.7.0 - bs58: 4.0.1 - buffer: 6.0.3 - fast-stable-stringify: 1.0.0 - jayson: 4.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) - node-fetch: 2.7.0 - rpc-websockets: 9.0.2 - superstruct: 2.0.2 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - '@swc/helpers@0.5.12': - dependencies: - tslib: 2.6.2 - - '@types/bn.js@5.1.5': - dependencies: - '@types/node': 20.12.11 - - '@types/chai@4.3.16': {} - - '@types/connect@3.4.38': - dependencies: - '@types/node': 20.12.11 - - '@types/json5@0.0.29': - optional: true - - '@types/mocha@9.1.1': {} - - '@types/node@12.20.55': {} - - '@types/node@20.12.11': - dependencies: - undici-types: 5.26.5 - - '@types/uuid@8.3.4': {} - - '@types/ws@7.4.7': - dependencies: - '@types/node': 20.12.11 - - '@types/ws@8.5.12': - dependencies: - '@types/node': 20.12.11 - - '@ungap/promise-all-settled@1.1.2': {} - - JSONStream@1.3.5: - dependencies: - jsonparse: 1.3.1 - through: 2.3.8 - - agentkeepalive@4.5.0: - dependencies: - humanize-ms: 1.2.1 - - ansi-colors@4.1.1: {} - - ansi-regex@5.0.1: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - argparse@2.0.1: {} - - arrify@1.0.1: {} - - assertion-error@1.1.0: {} - - balanced-match@1.0.2: {} - - base-x@3.0.9: - dependencies: - safe-buffer: 5.2.1 - - base64-js@1.5.1: {} - - binary-extensions@2.3.0: {} - - bn.js@5.2.1: {} - - bn.js@5.2.2: {} - - borsh@0.7.0: - dependencies: - bn.js: 5.2.1 - bs58: 4.0.1 - text-encoding-utf-8: 1.0.2 - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - braces@3.0.2: - dependencies: - fill-range: 7.0.1 - - browser-stdout@1.3.1: {} - - bs58@4.0.1: - dependencies: - base-x: 3.0.9 - - buffer-from@1.1.2: {} - - buffer-layout@1.2.2: {} - - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - bufferutil@4.0.8: - dependencies: - node-gyp-build: 4.8.1 - optional: true - - camelcase@6.3.0: {} - - chai@4.4.1: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.3 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.0.8 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chalk@5.6.2: {} - - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 - - chokidar@3.5.3: - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - commander@14.0.2: {} - - commander@2.20.3: {} - - concat-map@0.0.1: {} - - cross-fetch@3.2.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - debug@4.3.3(supports-color@8.1.1): - dependencies: - ms: 2.1.2 - optionalDependencies: - supports-color: 8.1.1 - - decamelize@4.0.0: {} - - deep-eql@4.1.3: - dependencies: - type-detect: 4.0.8 - - delay@5.0.0: {} - - diff@3.5.0: {} - - diff@5.0.0: {} - - emoji-regex@8.0.0: {} - - es6-promise@4.2.8: {} - - es6-promisify@5.0.0: - dependencies: - es6-promise: 4.2.8 - - escalade@3.1.2: {} - - escape-string-regexp@4.0.0: {} - - eventemitter3@4.0.7: {} - - eventemitter3@5.0.1: {} - - eyes@0.1.8: {} - - fast-stable-stringify@1.0.0: {} - - fastestsmallesttextencoderdecoder@1.0.22: {} - - fill-range@7.0.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat@5.0.2: {} - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - get-caller-file@2.0.5: {} - - get-func-name@2.0.2: {} - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - growl@1.10.5: {} - - has-flag@4.0.0: {} - - he@1.2.0: {} - - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - - ieee754@1.2.1: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - is-plain-obj@2.1.0: {} - - is-unicode-supported@0.1.0: {} - - isexe@2.0.0: {} - - isomorphic-ws@4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)): - dependencies: - ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) - - jayson@4.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10): - dependencies: - '@types/connect': 3.4.38 - '@types/node': 12.20.55 - '@types/ws': 7.4.7 - JSONStream: 1.3.5 - commander: 2.20.3 - delay: 5.0.0 - es6-promisify: 5.0.0 - eyes: 0.1.8 - isomorphic-ws: 4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - json-stringify-safe: 5.0.1 - uuid: 8.3.2 - ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - json-stringify-safe@5.0.1: {} - - json5@1.0.2: - dependencies: - minimist: 1.2.8 - optional: true - - jsonparse@1.3.1: {} - - litesvm-darwin-arm64@0.4.0: - optional: true - - litesvm-darwin-x64@0.4.0: - optional: true - - litesvm-linux-arm64-gnu@0.4.0: - optional: true - - litesvm-linux-arm64-musl@0.4.0: - optional: true - - litesvm-linux-x64-gnu@0.4.0: - optional: true - - litesvm-linux-x64-musl@0.4.0: - optional: true - - litesvm@0.4.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10): - dependencies: - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - fastestsmallesttextencoderdecoder: 1.0.22 - optionalDependencies: - litesvm-darwin-arm64: 0.4.0 - litesvm-darwin-x64: 0.4.0 - litesvm-linux-arm64-gnu: 0.4.0 - litesvm-linux-arm64-musl: 0.4.0 - litesvm-linux-x64-gnu: 0.4.0 - litesvm-linux-x64-musl: 0.4.0 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - - make-error@1.3.6: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@4.2.1: - dependencies: - brace-expansion: 1.1.11 - - minimist@1.2.8: {} - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - mocha@9.2.2: - dependencies: - '@ungap/promise-all-settled': 1.1.2 - ansi-colors: 4.1.1 - browser-stdout: 1.3.1 - chokidar: 3.5.3 - debug: 4.3.3(supports-color@8.1.1) - diff: 5.0.0 - escape-string-regexp: 4.0.0 - find-up: 5.0.0 - glob: 7.2.0 - growl: 1.10.5 - he: 1.2.0 - js-yaml: 4.1.0 - log-symbols: 4.1.0 - minimatch: 4.2.1 - ms: 2.1.3 - nanoid: 3.3.1 - serialize-javascript: 6.0.0 - strip-json-comments: 3.1.1 - supports-color: 8.1.1 - which: 2.0.2 - workerpool: 6.2.0 - yargs: 16.2.0 - yargs-parser: 20.2.4 - yargs-unparser: 2.0.0 - - ms@2.1.2: {} - - ms@2.1.3: {} - - nanoid@3.3.1: {} - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - - node-gyp-build@4.8.1: - optional: true - - normalize-path@3.0.0: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - pako@2.1.0: {} - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - pathval@1.1.1: {} - - picomatch@2.3.1: {} - - prettier@2.8.8: {} - - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - regenerator-runtime@0.14.1: {} - - require-directory@2.1.1: {} - - rpc-websockets@9.0.2: - dependencies: - '@swc/helpers': 0.5.12 - '@types/uuid': 8.3.4 - '@types/ws': 8.5.12 - buffer: 6.0.3 - eventemitter3: 5.0.1 - uuid: 8.3.2 - ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - safe-buffer@5.2.1: {} - - serialize-javascript@6.0.0: - dependencies: - randombytes: 2.1.0 - - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-bom@3.0.0: - optional: true - - strip-json-comments@3.1.1: {} - - superstruct@0.15.5: {} - - superstruct@2.0.2: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - text-encoding-utf-8@1.0.2: {} - - through@2.3.8: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - toml@3.0.0: {} - - tr46@0.0.3: {} - - ts-mocha@10.0.0(mocha@9.2.2): - dependencies: - mocha: 9.2.2 - ts-node: 7.0.1 - optionalDependencies: - tsconfig-paths: 3.15.0 - - ts-node@7.0.1: - dependencies: - arrify: 1.0.1 - buffer-from: 1.1.2 - diff: 3.5.0 - make-error: 1.3.6 - minimist: 1.2.8 - mkdirp: 0.5.6 - source-map-support: 0.5.21 - yn: 2.0.0 - - tsconfig-paths@3.15.0: - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - optional: true - - tslib@2.6.2: {} - - type-detect@4.0.8: {} - - typescript@5.9.3: {} - - undici-types@5.26.5: {} - - utf-8-validate@5.0.10: - dependencies: - node-gyp-build: 4.8.1 - optional: true - - uuid@8.3.2: {} - - webidl-conversions@3.0.1: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - workerpool@6.2.0: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrappy@1.0.2: {} - - ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - y18n@5.0.8: {} - - yargs-parser@20.2.4: {} - - yargs-unparser@2.0.0: - dependencies: - camelcase: 6.3.0 - decamelize: 4.0.0 - flat: 5.0.2 - is-plain-obj: 2.1.0 - - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.4 - - yn@2.0.0: {} - - yocto-queue@0.1.0: {} diff --git a/basics/counter/anchor/programs/counter_anchor/Cargo.toml b/basics/counter/anchor/programs/counter_anchor/Cargo.toml index 5f0d1ce44..4cdeea22a 100644 --- a/basics/counter/anchor/programs/counter_anchor/Cargo.toml +++ b/basics/counter/anchor/programs/counter_anchor/Cargo.toml @@ -20,8 +20,14 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/counter/anchor/programs/counter_anchor/src/lib.rs b/basics/counter/anchor/programs/counter_anchor/src/lib.rs index 5e208eeb5..08d5c3078 100644 --- a/basics/counter/anchor/programs/counter_anchor/src/lib.rs +++ b/basics/counter/anchor/programs/counter_anchor/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("BmDHboaj1kBUoinJKKSRqKfMeRKJqQqEbUj1VgzeQe4A"); +declare_id!("9nG25nFpLsycMERePF627oKHm5cHvNyv2TbfiFck32EP"); #[program] pub mod counter_anchor { diff --git a/basics/counter/anchor/programs/counter_anchor/tests/test_counter.rs b/basics/counter/anchor/programs/counter_anchor/tests/test_counter.rs new file mode 100644 index 000000000..8a0648b3c --- /dev/null +++ b/basics/counter/anchor/programs/counter_anchor/tests/test_counter.rs @@ -0,0 +1,143 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, system_program}, + InstructionData, ToAccountMetas, + }, + borsh::BorshDeserialize, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +/// Minimal deserialization of the Counter account (8-byte discriminator + u64). +#[derive(BorshDeserialize)] +struct CounterAccount { + _discriminator: [u8; 8], + count: u64, +} + +fn setup() -> (LiteSVM, anchor_lang::prelude::Pubkey, Keypair) { + let program_id = counter_anchor::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/counter_anchor.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +fn fetch_counter(svm: &LiteSVM, counter_pubkey: &anchor_lang::prelude::Pubkey) -> u64 { + let account = svm.get_account(counter_pubkey).unwrap(); + let counter = CounterAccount::try_from_slice(&account.data).unwrap(); + counter.count +} + +#[test] +fn test_initialize_counter() { + let (mut svm, _program_id, payer) = setup(); + let counter_keypair = Keypair::new(); + + let instruction = Instruction::new_with_bytes( + counter_anchor::id(), + &counter_anchor::instruction::InitializeCounter {}.data(), + counter_anchor::accounts::InitializeCounter { + payer: payer.pubkey(), + counter: counter_keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &counter_keypair], + &payer.pubkey(), + ) + .unwrap(); + + let count = fetch_counter(&svm, &counter_keypair.pubkey()); + assert_eq!(count, 0, "Expected initialized count to be 0"); +} + +#[test] +fn test_increment_counter() { + let (mut svm, _program_id, payer) = setup(); + let counter_keypair = Keypair::new(); + + // Initialize + let init_ix = Instruction::new_with_bytes( + counter_anchor::id(), + &counter_anchor::instruction::InitializeCounter {}.data(), + counter_anchor::accounts::InitializeCounter { + payer: payer.pubkey(), + counter: counter_keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![init_ix], + &[&payer, &counter_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Increment + let inc_ix = Instruction::new_with_bytes( + counter_anchor::id(), + &counter_anchor::instruction::Increment {}.data(), + counter_anchor::accounts::Increment { + counter: counter_keypair.pubkey(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![inc_ix], &[&payer], &payer.pubkey()).unwrap(); + + let count = fetch_counter(&svm, &counter_keypair.pubkey()); + assert_eq!(count, 1, "Expected count to be 1"); +} + +#[test] +fn test_increment_counter_again() { + let (mut svm, _program_id, payer) = setup(); + let counter_keypair = Keypair::new(); + + // Initialize + let init_ix = Instruction::new_with_bytes( + counter_anchor::id(), + &counter_anchor::instruction::InitializeCounter {}.data(), + counter_anchor::accounts::InitializeCounter { + payer: payer.pubkey(), + counter: counter_keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![init_ix], + &[&payer, &counter_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Increment twice + for _ in 0..2 { + let inc_ix = Instruction::new_with_bytes( + counter_anchor::id(), + &counter_anchor::instruction::Increment {}.data(), + counter_anchor::accounts::Increment { + counter: counter_keypair.pubkey(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![inc_ix], &[&payer], &payer.pubkey()) + .unwrap(); + svm.expire_blockhash(); + } + + let count = fetch_counter(&svm, &counter_keypair.pubkey()); + assert_eq!(count, 2, "Expected count to be 2"); +} diff --git a/basics/counter/anchor/tests/litesvm.test.ts b/basics/counter/anchor/tests/litesvm.test.ts deleted file mode 100644 index 90e80ad85..000000000 --- a/basics/counter/anchor/tests/litesvm.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -import anchor from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; -import { assert } from "chai"; -import { LiteSVM } from "litesvm"; -import IDL from "../target/idl/counter_anchor.json" with { type: "json" }; - -describe("LiteSVM: Counter", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(IDL.address); - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(1000000000)); - - const coder = new anchor.BorshCoder(IDL as anchor.Idl); - const programPath = new URL( - "../target/deploy/counter_anchor.so", - import.meta.url, - ).pathname; - svm.addProgramFromFile(programId, programPath); - - /** - * Generate a new keypair for the counter account - */ - const counterKeypair = new Keypair(); - - it("Initialize Counter", () => { - /** - * Instruction data - * Create Transaction - */ - const data = coder.instruction.encode("initialize_counter", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: counterKeypair.publicKey, isSigner: true, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer, counterKeypair); - svm.sendTransaction(tx); - - /** - * Fetch counter account - */ - const counterAccount = svm.getAccount(counterKeypair.publicKey); - const counter = coder.accounts.decode( - "Counter", - Buffer.from(counterAccount.data), - ); - - assert.equal(counter.count, 0); - }); - - it("Increment Counter", () => { - const data = coder.instruction.encode("increment", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: counterKeypair.publicKey, isSigner: false, isWritable: true }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - svm.expireBlockhash(); - - /** - * Fetch counter account - */ - const counterAccount = svm.getAccount(counterKeypair.publicKey); - const counter = coder.accounts.decode( - "Counter", - Buffer.from(counterAccount.data), - ); - - assert.equal(counter.count, 1); - }); - - it("Increment Counter Again", () => { - const data = coder.instruction.encode("increment", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: counterKeypair.publicKey, isSigner: false, isWritable: true }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - - /** - * Fetch counter account - */ - const counterAccount = svm.getAccount(counterKeypair.publicKey); - const counter = coder.accounts.decode( - "Counter", - Buffer.from(counterAccount.data), - ); - - assert.equal(counter.count, 2); - }); -}); diff --git a/basics/counter/anchor/tests/test.ts b/basics/counter/anchor/tests/test.ts deleted file mode 100644 index 12f93fde9..000000000 --- a/basics/counter/anchor/tests/test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { Program } from "@anchor-lang/core"; -import * as anchor from "@anchor-lang/core"; -import { Keypair } from "@solana/web3.js"; -import { assert } from "chai"; -import type { CounterAnchor } from "../target/types/counter_anchor.ts"; - -describe("Anchor: Counter", () => { - // Configure the client to use the local cluster. - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - - const program = anchor.workspace.CounterAnchor as Program; - - // Generate a new keypair for the counter account - const counterKeypair = new Keypair(); - - it("Initialize Counter", async () => { - await program.methods - .initializeCounter() - .accounts({ - counter: counterKeypair.publicKey, - payer: payer.publicKey, - }) - .signers([counterKeypair]) - .rpc(); - - const currentCount = await program.account.counter.fetch( - counterKeypair.publicKey, - ); - - assert( - currentCount.count.toNumber() === 0, - "Expected initialized count to be 0", - ); - }); - - it("Increment Counter", async () => { - await program.methods - .increment() - .accounts({ counter: counterKeypair.publicKey }) - .rpc(); - - const currentCount = await program.account.counter.fetch( - counterKeypair.publicKey, - ); - - assert(currentCount.count.toNumber() === 1, "Expected count to be 1"); - }); - - it("Increment Counter Again", async () => { - await program.methods - .increment() - .accounts({ counter: counterKeypair.publicKey }) - .rpc(); - - const currentCount = await program.account.counter.fetch( - counterKeypair.publicKey, - ); - - assert(currentCount.count.toNumber() === 2, "Expected count to be 2"); - }); -}); diff --git a/basics/counter/anchor/tsconfig.json b/basics/counter/anchor/tsconfig.json deleted file mode 100644 index fdf5c04de..000000000 --- a/basics/counter/anchor/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2020"], - "module": "nodenext", - "target": "es2020", - "esModuleInterop": true - } -} diff --git a/basics/counter/mpl-stack/.solitarc.js b/basics/counter/mpl-stack/.solitarc.js index 74dc762c5..8ea5faec3 100644 --- a/basics/counter/mpl-stack/.solitarc.js +++ b/basics/counter/mpl-stack/.solitarc.js @@ -1,14 +1,14 @@ // @ts-check -const path = require('node:path'); +const path = require("node:path"); const programDir = path.join(__dirname); -const idlDir = path.join(__dirname, 'idl'); -const sdkDir = path.join(__dirname, 'ts', 'generated'); -const binaryInstallDir = path.join(__dirname, 'target', 'solita'); +const idlDir = path.join(__dirname, "idl"); +const sdkDir = path.join(__dirname, "ts", "generated"); +const binaryInstallDir = path.join(__dirname, "target", "solita"); module.exports = { - idlGenerator: 'shank', - programName: 'counter_mpl_stack', - programId: 'Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS', + idlGenerator: "shank", + programName: "counter_mpl_stack", + programId: "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS", idlDir, sdkDir, binaryInstallDir, diff --git a/basics/counter/mpl-stack/jest.config.js b/basics/counter/mpl-stack/jest.config.js index 3943c3dbb..4dd7c478d 100644 --- a/basics/counter/mpl-stack/jest.config.js +++ b/basics/counter/mpl-stack/jest.config.js @@ -1,6 +1,6 @@ module.exports = { - preset: 'ts-jest/presets/default', - testEnvironment: 'node', + preset: "ts-jest/presets/default", + testEnvironment: "node", testTimeout: 100000, - resolver: 'ts-jest-resolver', + resolver: "ts-jest-resolver", }; diff --git a/basics/counter/mpl-stack/tests/counter.test.ts b/basics/counter/mpl-stack/tests/counter.test.ts index c3c3c99f1..dc345a80b 100644 --- a/basics/counter/mpl-stack/tests/counter.test.ts +++ b/basics/counter/mpl-stack/tests/counter.test.ts @@ -1,4 +1,4 @@ -import type { bignum } from '@metaplex-foundation/beet'; +import type { bignum } from "@metaplex-foundation/beet"; import { Connection, Keypair, @@ -7,20 +7,20 @@ import { sendAndConfirmTransaction, Transaction, type TransactionInstruction, -} from '@solana/web3.js'; -import { BN } from 'bn.js'; -import { assert } from 'chai'; +} from "@solana/web3.js"; +import { BN } from "bn.js"; +import { assert } from "chai"; -import { Counter, createIncrementInstruction, PROGRAM_ID } from '../ts'; +import { Counter, createIncrementInstruction, PROGRAM_ID } from "../ts"; function convertBignumToNumber(bignum: bignum): number { return new BN(bignum).toNumber(); } -describe('Counter Solana Native', () => { - const connection = new Connection('http://localhost:8899'); +describe("Counter Solana Native", () => { + const connection = new Connection("http://localhost:8899"); - it('Test allocate counter + increment tx', async () => { + it("Test allocate counter + increment tx", async () => { // Randomly generate our wallet const payerKeypair = Keypair.generate(); const payer = payerKeypair.publicKey; @@ -50,17 +50,20 @@ describe('Counter Solana Native', () => { tx.feePayer = payer; // Fetch a "timestamp" so validators know this is a recent transaction - tx.recentBlockhash = (await connection.getLatestBlockhash('confirmed')).blockhash; + tx.recentBlockhash = (await connection.getLatestBlockhash("confirmed")).blockhash; // Send transaction to network (local network) - await sendAndConfirmTransaction(connection, tx, [payerKeypair, counterKeypair], { skipPreflight: true, commitment: 'confirmed' }); + await sendAndConfirmTransaction(connection, tx, [payerKeypair, counterKeypair], { + skipPreflight: true, + commitment: "confirmed", + }); // Get the counter account info from network const count = (await Counter.fromAccountAddress(connection, counter)).count; - assert(new BN(count).toNumber() === 1, 'Expected count to have been 1'); + assert(new BN(count).toNumber() === 1, "Expected count to have been 1"); console.log(`[alloc+increment] count is: ${count}`); }); - it('Test allocate tx and increment tx', async () => { + it("Test allocate tx and increment tx", async () => { const payerKeypair = Keypair.generate(); const payer = payerKeypair.publicKey; @@ -79,11 +82,14 @@ describe('Counter Solana Native', () => { }); let tx = new Transaction().add(allocIx); tx.feePayer = payer; - tx.recentBlockhash = (await connection.getLatestBlockhash('confirmed')).blockhash; - await sendAndConfirmTransaction(connection, tx, [payerKeypair, counterKeypair], { skipPreflight: true, commitment: 'confirmed' }); + tx.recentBlockhash = (await connection.getLatestBlockhash("confirmed")).blockhash; + await sendAndConfirmTransaction(connection, tx, [payerKeypair, counterKeypair], { + skipPreflight: true, + commitment: "confirmed", + }); let count = (await Counter.fromAccountAddress(connection, counter)).count; - assert(convertBignumToNumber(count) === 0, 'Expected count to have been 0'); + assert(convertBignumToNumber(count) === 0, "Expected count to have been 0"); console.log(`[allocate] count is: ${count}`); // Check increment tx @@ -92,14 +98,14 @@ describe('Counter Solana Native', () => { }); tx = new Transaction().add(incrementIx); tx.feePayer = payer; - tx.recentBlockhash = (await connection.getLatestBlockhash('confirmed')).blockhash; + tx.recentBlockhash = (await connection.getLatestBlockhash("confirmed")).blockhash; await sendAndConfirmTransaction(connection, tx, [payerKeypair], { skipPreflight: true, - commitment: 'confirmed', + commitment: "confirmed", }); count = (await Counter.fromAccountAddress(connection, counter)).count; - assert(convertBignumToNumber(count) === 1, 'Expected count to have been 1'); + assert(convertBignumToNumber(count) === 1, "Expected count to have been 1"); console.log(`[increment] count is: ${count}`); }); }); diff --git a/basics/counter/mpl-stack/ts/generated/accounts/Counter.ts b/basics/counter/mpl-stack/ts/generated/accounts/Counter.ts index 8595a99e1..159e2972f 100644 --- a/basics/counter/mpl-stack/ts/generated/accounts/Counter.ts +++ b/basics/counter/mpl-stack/ts/generated/accounts/Counter.ts @@ -5,9 +5,9 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; -import * as beetSolana from '@metaplex-foundation/beet-solana'; -import * as web3 from '@solana/web3.js'; +import * as beet from "@metaplex-foundation/beet"; +import * as beetSolana from "@metaplex-foundation/beet-solana"; +import * as web3 from "@solana/web3.js"; /** * Arguments used to create {@link Counter} @@ -50,7 +50,7 @@ export class Counter implements CounterArgs { */ static async fromAccountAddress(connection: web3.Connection, address: web3.PublicKey): Promise { const accountInfo = await connection.getAccountInfo(address, { - commitment: 'confirmed', + commitment: "confirmed", }); if (accountInfo == null) { throw new Error(`Unable to find Counter account at ${address}`); @@ -64,7 +64,7 @@ export class Counter implements CounterArgs { * * @param programId - the program that owns the accounts we are filtering */ - static gpaBuilder(programId: web3.PublicKey = new web3.PublicKey('Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS')) { + static gpaBuilder(programId: web3.PublicKey = new web3.PublicKey("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS")) { return beetSolana.GpaBuilder.fromStruct(programId, counterBeet); } @@ -98,7 +98,10 @@ export class Counter implements CounterArgs { * * @param connection used to retrieve the rent exemption information */ - static async getMinimumBalanceForRentExemption(connection: web3.Connection, commitment?: web3.Commitment): Promise { + static async getMinimumBalanceForRentExemption( + connection: web3.Connection, + commitment?: web3.Commitment, + ): Promise { return connection.getMinimumBalanceForRentExemption(Counter.byteSize, commitment); } @@ -118,7 +121,7 @@ export class Counter implements CounterArgs { return { count: (() => { const x = <{ toNumber: () => number }>this.count; - if (typeof x.toNumber === 'function') { + if (typeof x.toNumber === "function") { try { return x.toNumber(); } catch (_) { @@ -135,4 +138,8 @@ export class Counter implements CounterArgs { * @category Accounts * @category generated */ -export const counterBeet = new beet.BeetStruct([['count', beet.u64]], Counter.fromArgs, 'Counter'); +export const counterBeet = new beet.BeetStruct( + [["count", beet.u64]], + Counter.fromArgs, + "Counter", +); diff --git a/basics/counter/mpl-stack/ts/generated/accounts/index.ts b/basics/counter/mpl-stack/ts/generated/accounts/index.ts index cea7bf897..4a7382443 100644 --- a/basics/counter/mpl-stack/ts/generated/accounts/index.ts +++ b/basics/counter/mpl-stack/ts/generated/accounts/index.ts @@ -1,5 +1,5 @@ -export * from './Counter'; +export * from "./Counter"; -import { Counter } from './Counter'; +import { Counter } from "./Counter"; export const accountProviders = { Counter }; diff --git a/basics/counter/mpl-stack/ts/generated/index.ts b/basics/counter/mpl-stack/ts/generated/index.ts index 1167eac99..8a3d97033 100644 --- a/basics/counter/mpl-stack/ts/generated/index.ts +++ b/basics/counter/mpl-stack/ts/generated/index.ts @@ -1,7 +1,7 @@ -import { PublicKey } from '@solana/web3.js'; +import { PublicKey } from "@solana/web3.js"; -export * from './accounts'; -export * from './instructions'; +export * from "./accounts"; +export * from "./instructions"; /** * Program address @@ -9,7 +9,7 @@ export * from './instructions'; * @category constants * @category generated */ -export const PROGRAM_ADDRESS = 'Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS'; +export const PROGRAM_ADDRESS = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"; /** * Program public key diff --git a/basics/counter/mpl-stack/ts/generated/instructions/Increment.ts b/basics/counter/mpl-stack/ts/generated/instructions/Increment.ts index 9f9e542fa..afc814560 100644 --- a/basics/counter/mpl-stack/ts/generated/instructions/Increment.ts +++ b/basics/counter/mpl-stack/ts/generated/instructions/Increment.ts @@ -5,8 +5,8 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; -import * as web3 from '@solana/web3.js'; +import * as beet from "@metaplex-foundation/beet"; +import * as web3 from "@solana/web3.js"; /** * @category Instructions @@ -15,7 +15,7 @@ import * as web3 from '@solana/web3.js'; */ export const IncrementStruct = new beet.BeetArgsStruct<{ instructionDiscriminator: number; -}>([['instructionDiscriminator', beet.u8]], 'IncrementInstructionArgs'); +}>([["instructionDiscriminator", beet.u8]], "IncrementInstructionArgs"); /** * Accounts required by the _Increment_ instruction * @@ -40,7 +40,7 @@ export const incrementInstructionDiscriminator = 0; */ export function createIncrementInstruction( accounts: IncrementInstructionAccounts, - programId = new web3.PublicKey('Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS'), + programId = new web3.PublicKey("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"), ) { const [data] = IncrementStruct.serialize({ instructionDiscriminator: incrementInstructionDiscriminator, diff --git a/basics/counter/mpl-stack/ts/generated/instructions/index.ts b/basics/counter/mpl-stack/ts/generated/instructions/index.ts index b9941ec47..84936e742 100644 --- a/basics/counter/mpl-stack/ts/generated/instructions/index.ts +++ b/basics/counter/mpl-stack/ts/generated/instructions/index.ts @@ -1 +1 @@ -export * from './Increment'; +export * from "./Increment"; diff --git a/basics/counter/mpl-stack/ts/index.ts b/basics/counter/mpl-stack/ts/index.ts index 69e4e4eb8..e84c86c64 100644 --- a/basics/counter/mpl-stack/ts/index.ts +++ b/basics/counter/mpl-stack/ts/index.ts @@ -1 +1 @@ -export * from './generated'; +export * from "./generated"; diff --git a/basics/counter/native/program/Cargo.toml b/basics/counter/native/program/Cargo.toml index 0180bb481..c928d7806 100644 --- a/basics/counter/native/program/Cargo.toml +++ b/basics/counter/native/program/Cargo.toml @@ -22,7 +22,7 @@ solana-program.workspace = true unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/counter/native/tests/counter.test.ts b/basics/counter/native/tests/counter.test.ts index 44c2056bf..97784546b 100644 --- a/basics/counter/native/tests/counter.test.ts +++ b/basics/counter/native/tests/counter.test.ts @@ -1,19 +1,19 @@ -import { describe, test } from 'node:test'; -import { Keypair, SystemProgram, Transaction, type TransactionInstruction } from '@solana/web3.js'; -import { assert } from 'chai'; -import { start } from 'solana-bankrun'; -import { COUNTER_ACCOUNT_SIZE, createIncrementInstruction, deserializeCounterAccount, PROGRAM_ID } from '../ts'; +import { describe, test } from "node:test"; +import { Keypair, SystemProgram, Transaction, type TransactionInstruction } from "@solana/web3.js"; +import { assert } from "chai"; +import { start } from "solana-bankrun"; +import { COUNTER_ACCOUNT_SIZE, createIncrementInstruction, deserializeCounterAccount, PROGRAM_ID } from "../ts"; -describe('Counter Solana Native', async () => { +describe("Counter Solana Native", async () => { // Randomly generate the program keypair and load the program to solana-bankrun - const context = await start([{ name: 'counter_solana_native', programId: PROGRAM_ID }], []); + const context = await start([{ name: "counter_solana_native", programId: PROGRAM_ID }], []); const client = context.banksClient; // Get the payer keypair from the context, this will be used to sign transactions with enough lamports const payer = context.payer; // Get the rent object to calculate rent for the accounts const rent = await client.getRent(); - test('Test allocate counter + increment tx', async () => { + test("Test allocate counter + increment tx", async () => { // Randomly generate the account key // to sign for setting up the Counter state const counterKeypair = Keypair.generate(); @@ -45,15 +45,15 @@ describe('Counter Solana Native', async () => { // Get the counter account info from network const counterAccountInfo = await client.getAccount(counter); - assert(counterAccountInfo, 'Expected counter account to have been created'); + assert(counterAccountInfo, "Expected counter account to have been created"); // Deserialize the counter & check count has been incremented const counterAccount = deserializeCounterAccount(Buffer.from(counterAccountInfo.data)); - assert(counterAccount.count.toNumber() === 1, 'Expected count to have been 1'); + assert(counterAccount.count.toNumber() === 1, "Expected count to have been 1"); console.log(`[alloc+increment] count is: ${counterAccount.count.toNumber()}`); }); - test('Test allocate tx and increment tx', async () => { + test("Test allocate tx and increment tx", async () => { const counterKeypair = Keypair.generate(); const counter = counterKeypair.publicKey; @@ -74,10 +74,10 @@ describe('Counter Solana Native', async () => { await client.processTransaction(tx); let counterAccountInfo = await client.getAccount(counter); - assert(counterAccountInfo, 'Expected counter account to have been created'); + assert(counterAccountInfo, "Expected counter account to have been created"); let counterAccount = deserializeCounterAccount(Buffer.from(counterAccountInfo.data)); - assert(counterAccount.count.toNumber() === 0, 'Expected count to have been 0'); + assert(counterAccount.count.toNumber() === 0, "Expected count to have been 0"); console.log(`[allocate] count is: ${counterAccount.count.toNumber()}`); // Check increment tx @@ -90,10 +90,10 @@ describe('Counter Solana Native', async () => { await client.processTransaction(tx); counterAccountInfo = await client.getAccount(counter); - assert(counterAccountInfo, 'Expected counter account to have been created'); + assert(counterAccountInfo, "Expected counter account to have been created"); counterAccount = deserializeCounterAccount(Buffer.from(counterAccountInfo.data)); - assert(counterAccount.count.toNumber() === 1, 'Expected count to have been 1'); + assert(counterAccount.count.toNumber() === 1, "Expected count to have been 1"); console.log(`[increment] count is: ${counterAccount.count.toNumber()}`); }); }); diff --git a/basics/counter/native/ts/accounts/counter.ts b/basics/counter/native/ts/accounts/counter.ts index 04b7f4844..e89747f9d 100644 --- a/basics/counter/native/ts/accounts/counter.ts +++ b/basics/counter/native/ts/accounts/counter.ts @@ -1,4 +1,4 @@ -import BN from 'bn.js'; +import BN from "bn.js"; export type Counter = { count: BN; @@ -8,10 +8,10 @@ export const COUNTER_ACCOUNT_SIZE = 8; export function deserializeCounterAccount(data: Buffer): Counter { if (data.byteLength !== 8) { - throw Error('Need exactly 8 bytes to deserialize counter'); + throw Error("Need exactly 8 bytes to deserialize counter"); } return { - count: new BN(data, 'le'), + count: new BN(data, "le"), }; } diff --git a/basics/counter/native/ts/accounts/index.ts b/basics/counter/native/ts/accounts/index.ts index 0ab63758b..bd1575cbc 100644 --- a/basics/counter/native/ts/accounts/index.ts +++ b/basics/counter/native/ts/accounts/index.ts @@ -1 +1 @@ -export * from './counter'; +export * from "./counter"; diff --git a/basics/counter/native/ts/index.ts b/basics/counter/native/ts/index.ts index 2322a115f..b353a01ff 100644 --- a/basics/counter/native/ts/index.ts +++ b/basics/counter/native/ts/index.ts @@ -1,6 +1,6 @@ -import { PublicKey } from '@solana/web3.js'; +import { PublicKey } from "@solana/web3.js"; -export * from './accounts'; -export * from './instructions'; +export * from "./accounts"; +export * from "./instructions"; -export const PROGRAM_ID = new PublicKey('Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS'); +export const PROGRAM_ID = new PublicKey("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"); diff --git a/basics/counter/native/ts/instructions/createIncrementInstruction.ts b/basics/counter/native/ts/instructions/createIncrementInstruction.ts index 6e0bf48c4..b7290acf7 100644 --- a/basics/counter/native/ts/instructions/createIncrementInstruction.ts +++ b/basics/counter/native/ts/instructions/createIncrementInstruction.ts @@ -1,5 +1,5 @@ -import { type PublicKey, TransactionInstruction } from '@solana/web3.js'; -import { PROGRAM_ID } from '../'; +import { type PublicKey, TransactionInstruction } from "@solana/web3.js"; +import { PROGRAM_ID } from "../"; export type IncrementInstructionAccounts = { counter: PublicKey; diff --git a/basics/counter/native/ts/instructions/index.ts b/basics/counter/native/ts/instructions/index.ts index a0249a40c..618dcd823 100644 --- a/basics/counter/native/ts/instructions/index.ts +++ b/basics/counter/native/ts/instructions/index.ts @@ -1 +1 @@ -export * from './createIncrementInstruction'; +export * from "./createIncrementInstruction"; diff --git a/basics/counter/pinocchio/program/Cargo.toml b/basics/counter/pinocchio/program/Cargo.toml index 54ffc5008..2df97c688 100644 --- a/basics/counter/pinocchio/program/Cargo.toml +++ b/basics/counter/pinocchio/program/Cargo.toml @@ -22,7 +22,7 @@ pinocchio-pubkey.workspace = true unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/counter/pinocchio/tests/counter.test.ts b/basics/counter/pinocchio/tests/counter.test.ts index c8ddf656f..a8e57d960 100644 --- a/basics/counter/pinocchio/tests/counter.test.ts +++ b/basics/counter/pinocchio/tests/counter.test.ts @@ -1,12 +1,4 @@ -import { describe, test } from "node:test"; -import { - Keypair, - SystemProgram, - Transaction, - type TransactionInstruction, -} from "@solana/web3.js"; -import { assert } from "chai"; -import { start } from "solana-bankrun"; +import { describe } from "node:test"; describe("Counter Solana Pinocchio", async () => { console.log("Counter Solana Pinocchio"); diff --git a/basics/create-account/anchor/Anchor.toml b/basics/create-account/anchor/Anchor.toml index 920804801..2aaa629f4 100644 --- a/basics/create-account/anchor/Anchor.toml +++ b/basics/create-account/anchor/Anchor.toml @@ -2,17 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false [programs.localnet] -create_system_account = "ARVNCsYKDQsCLHbwUTJLpFXVrJdjhWZStyzvxmKe2xHi" - -# [registry] section removed — no longer used in Anchor 1.0 +create_system_account = "ALfCAvL1Vbm15QabQJ72NUi7LK7fB5YP2tDKEvvh7wS8" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/create-account/anchor/package.json b/basics/create-account/anchor/package.json deleted file mode 100644 index 0432a3a0d..000000000 --- a/basics/create-account/anchor/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.4.1", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } -} diff --git a/basics/create-account/anchor/pnpm-lock.yaml b/basics/create-account/anchor/pnpm-lock.yaml deleted file mode 100644 index 78092f214..000000000 --- a/basics/create-account/anchor/pnpm-lock.yaml +++ /dev/null @@ -1,1466 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/web3.js': - specifier: ^1.98.4 - version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - litesvm: - specifier: ^0.4.0 - version: 0.4.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - devDependencies: - '@types/bn.js': - specifier: ^5.1.0 - version: 5.1.5 - '@types/chai': - specifier: ^4.3.0 - version: 4.3.16 - '@types/mocha': - specifier: ^9.0.0 - version: 9.1.1 - chai: - specifier: ^4.4.1 - version: 4.4.1 - mocha: - specifier: ^9.0.3 - version: 9.2.2 - ts-mocha: - specifier: ^10.0.0 - version: 10.0.0(mocha@9.2.2) - typescript: - specifier: ^5.3.3 - version: 5.9.3 - -packages: - - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} - engines: {node: '>=10'} - peerDependencies: - '@solana/web3.js': ^1.69.0 - - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} - engines: {node: '>=17'} - - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} - engines: {node: '>=10'} - - '@babel/runtime@7.25.0': - resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==} - engines: {node: '>=6.9.0'} - - '@noble/curves@1.5.0': - resolution: {integrity: sha512-J5EKamIHnKPyClwVrzmaf5wSdQXgdHcPZIZLu3bwnbeCx8/7NPK5q2ZBWF+5FvYGByjiQQsJYX6jfgB2wDPn3A==} - - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - - '@noble/hashes@1.8.0': - resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} - engines: {node: ^14.21.3 || >=16} - - '@solana/buffer-layout@4.0.1': - resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} - engines: {node: '>=5.10'} - - '@solana/codecs-core@2.3.0': - resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==} - engines: {node: '>=20.18.0'} - peerDependencies: - typescript: '>=5.3.3' - - '@solana/codecs-numbers@2.3.0': - resolution: {integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==} - engines: {node: '>=20.18.0'} - peerDependencies: - typescript: '>=5.3.3' - - '@solana/errors@2.3.0': - resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==} - engines: {node: '>=20.18.0'} - hasBin: true - peerDependencies: - typescript: '>=5.3.3' - - '@solana/web3.js@1.98.4': - resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==} - - '@swc/helpers@0.5.12': - resolution: {integrity: sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==} - - '@types/bn.js@5.1.5': - resolution: {integrity: sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==} - - '@types/chai@4.3.16': - resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} - - '@types/connect@3.4.38': - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - - '@types/mocha@9.1.1': - resolution: {integrity: sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==} - - '@types/node@12.20.55': - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - - '@types/node@20.12.11': - resolution: {integrity: sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==} - - '@types/uuid@8.3.4': - resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} - - '@types/ws@7.4.7': - resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} - - '@types/ws@8.5.12': - resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} - - '@ungap/promise-all-settled@1.1.2': - resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} - - JSONStream@1.3.5: - resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} - hasBin: true - - agentkeepalive@4.5.0: - resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} - engines: {node: '>= 8.0.0'} - - ansi-colors@4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} - engines: {node: '>=6'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base-x@3.0.9: - resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - bn.js@5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - - bn.js@5.2.2: - resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} - - borsh@0.7.0: - resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - - browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - - bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - buffer-layout@1.2.2: - resolution: {integrity: sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==} - engines: {node: '>=4.5'} - - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - bufferutil@4.0.8: - resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} - engines: {node: '>=6.14.2'} - - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chalk@5.6.2: - resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - - chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - commander@14.0.2: - resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} - engines: {node: '>=20'} - - commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - cross-fetch@3.2.0: - resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} - - debug@4.3.3: - resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - - deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} - - delay@5.0.0: - resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} - engines: {node: '>=10'} - - diff@3.5.0: - resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} - engines: {node: '>=0.3.1'} - - diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - es6-promise@4.2.8: - resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} - - es6-promisify@5.0.0: - resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - - eyes@0.1.8: - resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} - engines: {node: '> 0.1.90'} - - fast-stable-stringify@1.0.0: - resolution: {integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==} - - fastestsmallesttextencoderdecoder@1.0.22: - resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} - - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob@7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} - - growl@1.10.5: - resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==} - engines: {node: '>=4.x'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - isomorphic-ws@4.0.1: - resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} - peerDependencies: - ws: '*' - - jayson@4.1.1: - resolution: {integrity: sha512-5ZWm4Q/0DHPyeMfAsrwViwUS2DMVsQgWh8bEEIVTkfb3DzHZ2L3G5WUnF+AKmGjjM9r1uAv73SaqC1/U4RL45w==} - engines: {node: '>=8'} - hasBin: true - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - - json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - - jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - - litesvm-darwin-arm64@0.4.0: - resolution: {integrity: sha512-LN6iZcUQ6Xi5KO/7yJBYSALjjDCI/s/s2PgV3BqM4dpeBaLz+fXX/+qgMcBgpEVgEdEmhelux+WtAMkbEzJfrA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - litesvm-darwin-x64@0.4.0: - resolution: {integrity: sha512-3ltogKQdle8LbakVqoB6plxaNwp6Vb3tnkqa3G5mAvvZNorB2iumThDaTZ381Knl69t566LZm+g/VDZwYfsfhA==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] - - litesvm-linux-arm64-gnu@0.4.0: - resolution: {integrity: sha512-SWlcRUqkXCMgLoDX/Wqr/S1lff+ggVI9f0YrRJMraxtEyApxutAoW2AWw4tvo6DsEgNwjxgsZOAwnE6bQBv8CA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - litesvm-linux-arm64-musl@0.4.0: - resolution: {integrity: sha512-YMMqwEWJUSWwL0Rwp8dFwl3jvgNU21eI7Qc+BpH9u2yeIRYQTn3rNGDnsK8v3QIZPHQdMo7NrPhzk4XoB1aKPg==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [musl] - - litesvm-linux-x64-gnu@0.4.0: - resolution: {integrity: sha512-brZ3tFABDVQEYCgci7AO8iVYLw10UXVo97/lpTy75bTzNoqkggg8wFQOrbgCdb9NRwt06Y4Zf8cpIZAoDQq2mw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [glibc] - - litesvm-linux-x64-musl@0.4.0: - resolution: {integrity: sha512-D98qdIOuWg4fOewIIiH1D23AtM4I7/3vLKXIL8uQz06D5ev5fsBzNp2gM7libAywTkCYy/u666xgD6PsWhrTaw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [musl] - - litesvm@0.4.0: - resolution: {integrity: sha512-ySr5mB2ap4SzJpmVR2I5+gjzTH8NJbkg7DYPormzA2U9F4LhfvTTrD17X/k5N3Bn4b5Db6/CwSyX2qc0HrJtNA==} - engines: {node: '>= 20'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@4.2.1: - resolution: {integrity: sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==} - engines: {node: '>=10'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - mocha@9.2.2: - resolution: {integrity: sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==} - engines: {node: '>= 12.0.0'} - hasBin: true - - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.1: - resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - - node-gyp-build@4.8.1: - resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} - hasBin: true - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - pako@2.1.0: - resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - rpc-websockets@9.0.2: - resolution: {integrity: sha512-YzggvfItxMY3Lwuax5rC18inhbjJv9Py7JXRHxTIi94JOLrqBsSsUUc5bbl5W6c11tXhdfpDPK0KzBhoGe8jjw==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - serialize-javascript@6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} - - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - superstruct@0.15.5: - resolution: {integrity: sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==} - - superstruct@2.0.2: - resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} - engines: {node: '>=14.0.0'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - text-encoding-utf-8@1.0.2: - resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} - - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - toml@3.0.0: - resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} - - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - ts-mocha@10.0.0: - resolution: {integrity: sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw==} - engines: {node: '>= 6.X.X'} - hasBin: true - peerDependencies: - mocha: ^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X - - ts-node@7.0.1: - resolution: {integrity: sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==} - engines: {node: '>=4.2.0'} - hasBin: true - - tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - utf-8-validate@5.0.10: - resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} - engines: {node: '>=6.14.2'} - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - workerpool@6.2.0: - resolution: {integrity: sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yargs-parser@20.2.4: - resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} - engines: {node: '>=10'} - - yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} - - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - - yn@2.0.0: - resolution: {integrity: sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==} - engines: {node: '>=4'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': - dependencies: - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - bn.js: 5.2.2 - buffer-layout: 1.2.2 - - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 - '@noble/hashes': 1.8.0 - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - bn.js: 5.2.2 - bs58: 4.0.1 - buffer-layout: 1.2.2 - camelcase: 6.3.0 - cross-fetch: 3.2.0 - eventemitter3: 4.0.7 - pako: 2.1.0 - superstruct: 0.15.5 - toml: 3.0.0 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - '@anchor-lang/errors@1.0.0-rc.5': {} - - '@babel/runtime@7.25.0': - dependencies: - regenerator-runtime: 0.14.1 - - '@noble/curves@1.5.0': - dependencies: - '@noble/hashes': 1.4.0 - - '@noble/hashes@1.4.0': {} - - '@noble/hashes@1.8.0': {} - - '@solana/buffer-layout@4.0.1': - dependencies: - buffer: 6.0.3 - - '@solana/codecs-core@2.3.0(typescript@5.9.3)': - dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - - '@solana/codecs-numbers@2.3.0(typescript@5.9.3)': - dependencies: - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - - '@solana/errors@2.3.0(typescript@5.9.3)': - dependencies: - chalk: 5.6.2 - commander: 14.0.2 - typescript: 5.9.3 - - '@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@babel/runtime': 7.25.0 - '@noble/curves': 1.5.0 - '@noble/hashes': 1.4.0 - '@solana/buffer-layout': 4.0.1 - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) - agentkeepalive: 4.5.0 - bn.js: 5.2.1 - borsh: 0.7.0 - bs58: 4.0.1 - buffer: 6.0.3 - fast-stable-stringify: 1.0.0 - jayson: 4.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) - node-fetch: 2.7.0 - rpc-websockets: 9.0.2 - superstruct: 2.0.2 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - '@swc/helpers@0.5.12': - dependencies: - tslib: 2.6.2 - - '@types/bn.js@5.1.5': - dependencies: - '@types/node': 20.12.11 - - '@types/chai@4.3.16': {} - - '@types/connect@3.4.38': - dependencies: - '@types/node': 20.12.11 - - '@types/json5@0.0.29': - optional: true - - '@types/mocha@9.1.1': {} - - '@types/node@12.20.55': {} - - '@types/node@20.12.11': - dependencies: - undici-types: 5.26.5 - - '@types/uuid@8.3.4': {} - - '@types/ws@7.4.7': - dependencies: - '@types/node': 20.12.11 - - '@types/ws@8.5.12': - dependencies: - '@types/node': 20.12.11 - - '@ungap/promise-all-settled@1.1.2': {} - - JSONStream@1.3.5: - dependencies: - jsonparse: 1.3.1 - through: 2.3.8 - - agentkeepalive@4.5.0: - dependencies: - humanize-ms: 1.2.1 - - ansi-colors@4.1.1: {} - - ansi-regex@5.0.1: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - argparse@2.0.1: {} - - arrify@1.0.1: {} - - assertion-error@1.1.0: {} - - balanced-match@1.0.2: {} - - base-x@3.0.9: - dependencies: - safe-buffer: 5.2.1 - - base64-js@1.5.1: {} - - binary-extensions@2.3.0: {} - - bn.js@5.2.1: {} - - bn.js@5.2.2: {} - - borsh@0.7.0: - dependencies: - bn.js: 5.2.1 - bs58: 4.0.1 - text-encoding-utf-8: 1.0.2 - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - braces@3.0.2: - dependencies: - fill-range: 7.0.1 - - browser-stdout@1.3.1: {} - - bs58@4.0.1: - dependencies: - base-x: 3.0.9 - - buffer-from@1.1.2: {} - - buffer-layout@1.2.2: {} - - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - bufferutil@4.0.8: - dependencies: - node-gyp-build: 4.8.1 - optional: true - - camelcase@6.3.0: {} - - chai@4.4.1: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.3 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.0.8 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chalk@5.6.2: {} - - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 - - chokidar@3.5.3: - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - commander@14.0.2: {} - - commander@2.20.3: {} - - concat-map@0.0.1: {} - - cross-fetch@3.2.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - debug@4.3.3(supports-color@8.1.1): - dependencies: - ms: 2.1.2 - optionalDependencies: - supports-color: 8.1.1 - - decamelize@4.0.0: {} - - deep-eql@4.1.3: - dependencies: - type-detect: 4.0.8 - - delay@5.0.0: {} - - diff@3.5.0: {} - - diff@5.0.0: {} - - emoji-regex@8.0.0: {} - - es6-promise@4.2.8: {} - - es6-promisify@5.0.0: - dependencies: - es6-promise: 4.2.8 - - escalade@3.1.2: {} - - escape-string-regexp@4.0.0: {} - - eventemitter3@4.0.7: {} - - eventemitter3@5.0.1: {} - - eyes@0.1.8: {} - - fast-stable-stringify@1.0.0: {} - - fastestsmallesttextencoderdecoder@1.0.22: {} - - fill-range@7.0.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat@5.0.2: {} - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - get-caller-file@2.0.5: {} - - get-func-name@2.0.2: {} - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - growl@1.10.5: {} - - has-flag@4.0.0: {} - - he@1.2.0: {} - - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - - ieee754@1.2.1: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - is-plain-obj@2.1.0: {} - - is-unicode-supported@0.1.0: {} - - isexe@2.0.0: {} - - isomorphic-ws@4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)): - dependencies: - ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) - - jayson@4.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10): - dependencies: - '@types/connect': 3.4.38 - '@types/node': 12.20.55 - '@types/ws': 7.4.7 - JSONStream: 1.3.5 - commander: 2.20.3 - delay: 5.0.0 - es6-promisify: 5.0.0 - eyes: 0.1.8 - isomorphic-ws: 4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - json-stringify-safe: 5.0.1 - uuid: 8.3.2 - ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - json-stringify-safe@5.0.1: {} - - json5@1.0.2: - dependencies: - minimist: 1.2.8 - optional: true - - jsonparse@1.3.1: {} - - litesvm-darwin-arm64@0.4.0: - optional: true - - litesvm-darwin-x64@0.4.0: - optional: true - - litesvm-linux-arm64-gnu@0.4.0: - optional: true - - litesvm-linux-arm64-musl@0.4.0: - optional: true - - litesvm-linux-x64-gnu@0.4.0: - optional: true - - litesvm-linux-x64-musl@0.4.0: - optional: true - - litesvm@0.4.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10): - dependencies: - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - fastestsmallesttextencoderdecoder: 1.0.22 - optionalDependencies: - litesvm-darwin-arm64: 0.4.0 - litesvm-darwin-x64: 0.4.0 - litesvm-linux-arm64-gnu: 0.4.0 - litesvm-linux-arm64-musl: 0.4.0 - litesvm-linux-x64-gnu: 0.4.0 - litesvm-linux-x64-musl: 0.4.0 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - - make-error@1.3.6: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@4.2.1: - dependencies: - brace-expansion: 1.1.11 - - minimist@1.2.8: {} - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - mocha@9.2.2: - dependencies: - '@ungap/promise-all-settled': 1.1.2 - ansi-colors: 4.1.1 - browser-stdout: 1.3.1 - chokidar: 3.5.3 - debug: 4.3.3(supports-color@8.1.1) - diff: 5.0.0 - escape-string-regexp: 4.0.0 - find-up: 5.0.0 - glob: 7.2.0 - growl: 1.10.5 - he: 1.2.0 - js-yaml: 4.1.0 - log-symbols: 4.1.0 - minimatch: 4.2.1 - ms: 2.1.3 - nanoid: 3.3.1 - serialize-javascript: 6.0.0 - strip-json-comments: 3.1.1 - supports-color: 8.1.1 - which: 2.0.2 - workerpool: 6.2.0 - yargs: 16.2.0 - yargs-parser: 20.2.4 - yargs-unparser: 2.0.0 - - ms@2.1.2: {} - - ms@2.1.3: {} - - nanoid@3.3.1: {} - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - - node-gyp-build@4.8.1: - optional: true - - normalize-path@3.0.0: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - pako@2.1.0: {} - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - pathval@1.1.1: {} - - picomatch@2.3.1: {} - - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - regenerator-runtime@0.14.1: {} - - require-directory@2.1.1: {} - - rpc-websockets@9.0.2: - dependencies: - '@swc/helpers': 0.5.12 - '@types/uuid': 8.3.4 - '@types/ws': 8.5.12 - buffer: 6.0.3 - eventemitter3: 5.0.1 - uuid: 8.3.2 - ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - safe-buffer@5.2.1: {} - - serialize-javascript@6.0.0: - dependencies: - randombytes: 2.1.0 - - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-bom@3.0.0: - optional: true - - strip-json-comments@3.1.1: {} - - superstruct@0.15.5: {} - - superstruct@2.0.2: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - text-encoding-utf-8@1.0.2: {} - - through@2.3.8: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - toml@3.0.0: {} - - tr46@0.0.3: {} - - ts-mocha@10.0.0(mocha@9.2.2): - dependencies: - mocha: 9.2.2 - ts-node: 7.0.1 - optionalDependencies: - tsconfig-paths: 3.15.0 - - ts-node@7.0.1: - dependencies: - arrify: 1.0.1 - buffer-from: 1.1.2 - diff: 3.5.0 - make-error: 1.3.6 - minimist: 1.2.8 - mkdirp: 0.5.6 - source-map-support: 0.5.21 - yn: 2.0.0 - - tsconfig-paths@3.15.0: - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - optional: true - - tslib@2.6.2: {} - - type-detect@4.0.8: {} - - typescript@5.9.3: {} - - undici-types@5.26.5: {} - - utf-8-validate@5.0.10: - dependencies: - node-gyp-build: 4.8.1 - optional: true - - uuid@8.3.2: {} - - webidl-conversions@3.0.1: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - workerpool@6.2.0: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrappy@1.0.2: {} - - ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - y18n@5.0.8: {} - - yargs-parser@20.2.4: {} - - yargs-unparser@2.0.0: - dependencies: - camelcase: 6.3.0 - decamelize: 4.0.0 - flat: 5.0.2 - is-plain-obj: 2.1.0 - - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.4 - - yn@2.0.0: {} - - yocto-queue@0.1.0: {} diff --git a/basics/create-account/anchor/programs/create-system-account/Cargo.toml b/basics/create-account/anchor/programs/create-system-account/Cargo.toml index 25b52353b..afdfeaa37 100644 --- a/basics/create-account/anchor/programs/create-system-account/Cargo.toml +++ b/basics/create-account/anchor/programs/create-system-account/Cargo.toml @@ -20,8 +20,13 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/create-account/anchor/programs/create-system-account/src/lib.rs b/basics/create-account/anchor/programs/create-system-account/src/lib.rs index 644fc3004..04b2b187f 100644 --- a/basics/create-account/anchor/programs/create-system-account/src/lib.rs +++ b/basics/create-account/anchor/programs/create-system-account/src/lib.rs @@ -1,7 +1,7 @@ use anchor_lang::prelude::*; use anchor_lang::system_program::{create_account, CreateAccount}; -declare_id!("ARVNCsYKDQsCLHbwUTJLpFXVrJdjhWZStyzvxmKe2xHi"); +declare_id!("ALfCAvL1Vbm15QabQJ72NUi7LK7fB5YP2tDKEvvh7wS8"); #[program] pub mod create_system_account { diff --git a/basics/create-account/anchor/programs/create-system-account/tests/test_create_account.rs b/basics/create-account/anchor/programs/create-system-account/tests/test_create_account.rs new file mode 100644 index 000000000..7c1bcd4ff --- /dev/null +++ b/basics/create-account/anchor/programs/create-system-account/tests/test_create_account.rs @@ -0,0 +1,46 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, rent::Rent, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +#[test] +fn test_create_the_account() { + let program_id = create_system_account::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/create_system_account.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let new_account = Keypair::new(); + + let instruction = Instruction::new_with_bytes( + program_id, + &create_system_account::instruction::CreateSystemAccount {}.data(), + create_system_account::accounts::CreateSystemAccount { + payer: payer.pubkey(), + new_account: new_account.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &new_account], + &payer.pubkey(), + ) + .unwrap(); + + // Minimum balance for rent exemption for 0-data account + let lamports = Rent::default().minimum_balance(0); + + let account_info = svm.get_account(&new_account.pubkey()).unwrap(); + assert_eq!(account_info.lamports, lamports); +} diff --git a/basics/create-account/anchor/tests/litesvm.test.ts b/basics/create-account/anchor/tests/litesvm.test.ts deleted file mode 100644 index 36053080e..000000000 --- a/basics/create-account/anchor/tests/litesvm.test.ts +++ /dev/null @@ -1,64 +0,0 @@ -import anchor from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; -import { assert } from "chai"; -import { LiteSVM } from "litesvm"; -import IDL from "../target/idl/create_system_account.json" with { - type: "json", -}; - -describe("LiteSVM: Create a system account", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(IDL.address); - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(1000000000)); - - const coder = new anchor.BorshCoder(IDL as anchor.Idl); - const programPath = new URL( - "../target/deploy/create_system_account.so", - import.meta.url, - ).pathname; - svm.addProgramFromFile(programId, programPath); - - it("Create the account", () => { - /** - * Generate a new keypair for the new account - */ - const newKeypair = new Keypair(); - /** - * Instruction data - * Create Transaction - * Send Transaction - */ - const data = coder.instruction.encode("create_system_account", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: newKeypair.publicKey, isSigner: true, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer, newKeypair); - svm.sendTransaction(tx); - - /** - * Fetch account - * Check its lamports - * */ - const lamports = svm.minimumBalanceForRentExemption(0n); - const accountInfo = svm.getAccount(newKeypair.publicKey); - - assert(Number(lamports) === accountInfo.lamports); - }); -}); diff --git a/basics/create-account/anchor/tests/test.ts b/basics/create-account/anchor/tests/test.ts deleted file mode 100644 index 57a3cc900..000000000 --- a/basics/create-account/anchor/tests/test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import * as anchor from "@anchor-lang/core"; -import { Keypair } from "@solana/web3.js"; -import { assert } from "chai"; -import type { CreateSystemAccount } from "../target/types/create_system_account.ts"; - -describe("Anchor: Create a system account", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const wallet = provider.wallet as anchor.Wallet; - const connection = provider.connection; - const program = anchor.workspace - .CreateSystemAccount as anchor.Program; - - it("Create the account", async () => { - // Generate a new keypair for the new account - const newKeypair = new Keypair(); - - await program.methods - .createSystemAccount() - .accounts({ - payer: wallet.publicKey, - newAccount: newKeypair.publicKey, - }) - .signers([newKeypair]) - .rpc(); - - // Minimum balance for rent exemption for new account - const lamports = await connection.getMinimumBalanceForRentExemption(0); - - // Check that the account was created - const accountInfo = await connection.getAccountInfo(newKeypair.publicKey); - assert(accountInfo.lamports === lamports); - }); -}); diff --git a/basics/create-account/anchor/tsconfig.json b/basics/create-account/anchor/tsconfig.json deleted file mode 100644 index fdf5c04de..000000000 --- a/basics/create-account/anchor/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2020"], - "module": "nodenext", - "target": "es2020", - "esModuleInterop": true - } -} diff --git a/basics/create-account/native/program/Cargo.toml b/basics/create-account/native/program/Cargo.toml index 3bd473717..bde26597a 100644 --- a/basics/create-account/native/program/Cargo.toml +++ b/basics/create-account/native/program/Cargo.toml @@ -18,7 +18,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/create-account/native/tests/test.ts b/basics/create-account/native/tests/test.ts index 4c1068abb..0bc801bdd 100644 --- a/basics/create-account/native/tests/test.ts +++ b/basics/create-account/native/tests/test.ts @@ -1,4 +1,4 @@ -import { describe, test } from 'node:test'; +import { describe, test } from "node:test"; import { Keypair, LAMPORTS_PER_SOL, @@ -6,20 +6,17 @@ import { SystemProgram, Transaction, TransactionInstruction, -} from '@solana/web3.js'; -import { start } from 'solana-bankrun'; +} from "@solana/web3.js"; +import { start } from "solana-bankrun"; -describe('Create a system account', async () => { +describe("Create a system account", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start( - [{ name: 'create_account_program', programId: PROGRAM_ID }], - [], - ); + const context = await start([{ name: "create_account_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; - test('Create the account via a cross program invocation', async () => { + test("Create the account via a cross program invocation", async () => { const newKeypair = Keypair.generate(); const ix = new TransactionInstruction({ @@ -40,11 +37,11 @@ describe('Create a system account', async () => { await client.processTransaction(tx); // Verify the account was created - const accountInfo = await client.getAccount(newKeypair.publicKey); + const _accountInfo = await client.getAccount(newKeypair.publicKey); console.log(`Account with public key ${newKeypair.publicKey} successfully created via CPI`); }); - test('Create the account via direct call to system program', async () => { + test("Create the account via direct call to system program", async () => { const newKeypair = Keypair.generate(); const ix = SystemProgram.createAccount({ @@ -63,7 +60,7 @@ describe('Create a system account', async () => { await client.processTransaction(tx); // Verify the account was created - const accountInfo = await client.getAccount(newKeypair.publicKey); + const _accountInfo = await client.getAccount(newKeypair.publicKey); console.log(`Account with public key ${newKeypair.publicKey} successfully created`); }); }); diff --git a/basics/create-account/pinocchio/program/Cargo.toml b/basics/create-account/pinocchio/program/Cargo.toml index d6d61991a..609d465c2 100644 --- a/basics/create-account/pinocchio/program/Cargo.toml +++ b/basics/create-account/pinocchio/program/Cargo.toml @@ -20,7 +20,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/create-account/pinocchio/tests/test.ts b/basics/create-account/pinocchio/tests/test.ts index 3091b46e3..317ed75e1 100644 --- a/basics/create-account/pinocchio/tests/test.ts +++ b/basics/create-account/pinocchio/tests/test.ts @@ -11,10 +11,7 @@ import { start } from "solana-bankrun"; describe("Create a system account", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start( - [{ name: "create_account_pinocchio_program", programId: PROGRAM_ID }], - [], - ); + const context = await start([{ name: "create_account_pinocchio_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; @@ -56,8 +53,6 @@ describe("Create a system account", async () => { tx.add(ix).sign(payer, newKeypair); await client.processTransaction(tx); - console.log( - `Account with public key ${newKeypair.publicKey} successfully created`, - ); + console.log(`Account with public key ${newKeypair.publicKey} successfully created`); }); }); diff --git a/basics/cross-program-invocation/anchor/Anchor.toml b/basics/cross-program-invocation/anchor/Anchor.toml index 8134bd54e..ccd65289a 100644 --- a/basics/cross-program-invocation/anchor/Anchor.toml +++ b/basics/cross-program-invocation/anchor/Anchor.toml @@ -6,14 +6,14 @@ resolution = true skip-lint = false [programs.localnet] -hand = "Bi5N7SUQhpGknVcqPTzdFFVueQoxoUu8YTLz75J6fT8A" -lever = "E64FVeubGC4NPNF2UBJYX4AkrVowf74fRJD9q6YhwstN" - -# [registry] section removed — no longer used in Anchor 1.0 +hand = "4tvjFDZybFML3tN5uyRoHPoxUTitTwGxjD7KfKEmX7Vg" +lever = "3aP7aVaJck5pUzbh3t6cqyCPgk6otbiyHsNsXHzeNDE5" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/cross-program-invocation/anchor/idls/lever.json b/basics/cross-program-invocation/anchor/idls/lever.json index 3ec862d79..1372ab9df 100644 --- a/basics/cross-program-invocation/anchor/idls/lever.json +++ b/basics/cross-program-invocation/anchor/idls/lever.json @@ -1,5 +1,5 @@ { - "address": "E64FVeubGC4NPNF2UBJYX4AkrVowf74fRJD9q6YhwstN", + "address": "3aP7aVaJck5pUzbh3t6cqyCPgk6otbiyHsNsXHzeNDE5", "metadata": { "name": "lever", "version": "0.1.0", diff --git a/basics/cross-program-invocation/anchor/migrations/deploy.ts b/basics/cross-program-invocation/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/basics/cross-program-invocation/anchor/migrations/deploy.ts +++ b/basics/cross-program-invocation/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/basics/cross-program-invocation/anchor/package.json b/basics/cross-program-invocation/anchor/package.json index 6856081db..7f2afc3dc 100644 --- a/basics/cross-program-invocation/anchor/package.json +++ b/basics/cross-program-invocation/anchor/package.json @@ -1,22 +1,22 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/cross-program-invocation/anchor/pnpm-lock.yaml b/basics/cross-program-invocation/anchor/pnpm-lock.yaml index e9d23b11d..ab1ab1065 100644 --- a/basics/cross-program-invocation/anchor/pnpm-lock.yaml +++ b/basics/cross-program-invocation/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -45,18 +45,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': @@ -766,16 +766,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -793,7 +793,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: diff --git a/basics/cross-program-invocation/anchor/programs/hand/Cargo.toml b/basics/cross-program-invocation/anchor/programs/hand/Cargo.toml index ef3b6bd4f..51de9a266 100644 --- a/basics/cross-program-invocation/anchor/programs/hand/Cargo.toml +++ b/basics/cross-program-invocation/anchor/programs/hand/Cargo.toml @@ -20,8 +20,14 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/cross-program-invocation/anchor/programs/hand/src/lib.rs b/basics/cross-program-invocation/anchor/programs/hand/src/lib.rs index 2602e0e8d..f9b885d42 100644 --- a/basics/cross-program-invocation/anchor/programs/hand/src/lib.rs +++ b/basics/cross-program-invocation/anchor/programs/hand/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("Bi5N7SUQhpGknVcqPTzdFFVueQoxoUu8YTLz75J6fT8A"); +declare_id!("4tvjFDZybFML3tN5uyRoHPoxUTitTwGxjD7KfKEmX7Vg"); // automatically generate module using program idl found in ./idls declare_program!(lever); diff --git a/basics/cross-program-invocation/anchor/programs/hand/tests/test_hand.rs b/basics/cross-program-invocation/anchor/programs/hand/tests/test_hand.rs new file mode 100644 index 000000000..4a6d69ca6 --- /dev/null +++ b/basics/cross-program-invocation/anchor/programs/hand/tests/test_hand.rs @@ -0,0 +1,122 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::{AccountMeta, Instruction}, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +/// PowerStatus account layout: 8-byte discriminator + 1-byte bool + 7 bytes padding. +/// Account space is 8 + 8 = 16 bytes, so read the raw bytes instead of using BorshDeserialize +/// to avoid "Not all bytes read" errors from the padding. +fn read_power_is_on(svm: &LiteSVM, pubkey: &anchor_lang::prelude::Pubkey) -> bool { + let account = svm.get_account(pubkey).unwrap(); + // Skip 8-byte discriminator, read 1 byte for bool + account.data[8] != 0 +} + +/// Build the lever program's `initialize` instruction manually. +/// Discriminator from IDL: [175, 175, 109, 31, 13, 152, 155, 237] +fn build_lever_initialize_ix( + lever_program_id: anchor_lang::prelude::Pubkey, + power: anchor_lang::prelude::Pubkey, + user: anchor_lang::prelude::Pubkey, +) -> Instruction { + let discriminator: [u8; 8] = [175, 175, 109, 31, 13, 152, 155, 237]; + Instruction { + program_id: lever_program_id, + accounts: vec![ + AccountMeta::new(power, true), + AccountMeta::new(user, true), + AccountMeta::new_readonly(system_program::id(), false), + ], + data: discriminator.to_vec(), + } +} + +#[test] +fn test_pull_lever_cpi() { + let hand_program_id = hand::id(); + // The lever program ID from declare_program!(lever) inside hand crate + let lever_program_id = hand::lever::ID; + + let mut svm = LiteSVM::new(); + + // Load both programs + let hand_bytes = include_bytes!("../../../target/deploy/hand.so"); + let lever_bytes = include_bytes!("../../../target/deploy/lever.so"); + svm.add_program(hand_program_id, hand_bytes).unwrap(); + svm.add_program(lever_program_id, lever_bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let power_keypair = Keypair::new(); + + // Initialize the lever directly (manually constructed instruction) + let init_ix = + build_lever_initialize_ix(lever_program_id, power_keypair.pubkey(), payer.pubkey()); + send_transaction_from_instructions( + &mut svm, + vec![init_ix], + &[&payer, &power_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Verify initial state is off + assert!( + !read_power_is_on(&svm, &power_keypair.pubkey()), + "Power should be off after initialization" + ); + + // Pull the lever via the hand program (CPI into lever) + svm.expire_blockhash(); + let pull_ix = Instruction::new_with_bytes( + hand_program_id, + &hand::instruction::PullLever { + name: "Jacob".to_string(), + } + .data(), + hand::accounts::PullLever { + power: power_keypair.pubkey(), + lever_program: lever_program_id, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![pull_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + // Verify power is now on + assert!( + read_power_is_on(&svm, &power_keypair.pubkey()), + "Power should be on after pulling lever" + ); + + // Pull it again + svm.expire_blockhash(); + let pull_ix2 = Instruction::new_with_bytes( + hand_program_id, + &hand::instruction::PullLever { + name: "sol-warrior".to_string(), + } + .data(), + hand::accounts::PullLever { + power: power_keypair.pubkey(), + lever_program: lever_program_id, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![pull_ix2], &[&payer], &payer.pubkey()) + .unwrap(); + + // Verify power is now off again + assert!( + !read_power_is_on(&svm, &power_keypair.pubkey()), + "Power should be off after pulling lever again" + ); +} diff --git a/basics/cross-program-invocation/anchor/programs/lever/Cargo.toml b/basics/cross-program-invocation/anchor/programs/lever/Cargo.toml index 50e9488ce..52bcd14e1 100644 --- a/basics/cross-program-invocation/anchor/programs/lever/Cargo.toml +++ b/basics/cross-program-invocation/anchor/programs/lever/Cargo.toml @@ -20,8 +20,13 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/cross-program-invocation/anchor/programs/lever/src/lib.rs b/basics/cross-program-invocation/anchor/programs/lever/src/lib.rs index d3ebd3f3c..90a4f0c47 100644 --- a/basics/cross-program-invocation/anchor/programs/lever/src/lib.rs +++ b/basics/cross-program-invocation/anchor/programs/lever/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("E64FVeubGC4NPNF2UBJYX4AkrVowf74fRJD9q6YhwstN"); +declare_id!("3aP7aVaJck5pUzbh3t6cqyCPgk6otbiyHsNsXHzeNDE5"); #[program] pub mod lever { diff --git a/basics/cross-program-invocation/anchor/programs/lever/tests/test_lever.rs b/basics/cross-program-invocation/anchor/programs/lever/tests/test_lever.rs new file mode 100644 index 000000000..4cd3aec75 --- /dev/null +++ b/basics/cross-program-invocation/anchor/programs/lever/tests/test_lever.rs @@ -0,0 +1,124 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +/// PowerStatus account layout: 8-byte discriminator + 1-byte bool + 7 bytes padding. +/// Account space is 8 + 8 = 16 bytes, so read raw bytes to avoid "Not all bytes read" errors. +fn read_power_is_on(svm: &LiteSVM, pubkey: &anchor_lang::prelude::Pubkey) -> bool { + let account = svm.get_account(pubkey).unwrap(); + account.data[8] != 0 +} + +#[test] +fn test_initialize_lever() { + let program_id = lever::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/lever.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let power_keypair = Keypair::new(); + + let instruction = Instruction::new_with_bytes( + program_id, + &lever::instruction::Initialize {}.data(), + lever::accounts::InitializeLever { + power: power_keypair.pubkey(), + user: payer.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &power_keypair], + &payer.pubkey(), + ) + .unwrap(); + + assert!( + !read_power_is_on(&svm, &power_keypair.pubkey()), + "Power should be off after initialization" + ); +} + +#[test] +fn test_switch_power() { + let program_id = lever::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/lever.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let power_keypair = Keypair::new(); + + // Initialize + let init_ix = Instruction::new_with_bytes( + program_id, + &lever::instruction::Initialize {}.data(), + lever::accounts::InitializeLever { + power: power_keypair.pubkey(), + user: payer.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![init_ix], + &[&payer, &power_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Switch power on + let switch_ix = Instruction::new_with_bytes( + program_id, + &lever::instruction::SwitchPower { + name: "Alice".to_string(), + } + .data(), + lever::accounts::SetPowerStatus { + power: power_keypair.pubkey(), + } + .to_account_metas(None), + ); + svm.expire_blockhash(); + send_transaction_from_instructions(&mut svm, vec![switch_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + assert!( + read_power_is_on(&svm, &power_keypair.pubkey()), + "Power should be on after first switch" + ); + + // Switch power off + let switch_ix2 = Instruction::new_with_bytes( + program_id, + &lever::instruction::SwitchPower { + name: "Bob".to_string(), + } + .data(), + lever::accounts::SetPowerStatus { + power: power_keypair.pubkey(), + } + .to_account_metas(None), + ); + svm.expire_blockhash(); + send_transaction_from_instructions(&mut svm, vec![switch_ix2], &[&payer], &payer.pubkey()) + .unwrap(); + + assert!( + !read_power_is_on(&svm, &power_keypair.pubkey()), + "Power should be off after second switch" + ); +} diff --git a/basics/cross-program-invocation/anchor/tests/litesvm.test.ts b/basics/cross-program-invocation/anchor/tests/litesvm.test.ts index dcd966ddb..eb00f5312 100644 --- a/basics/cross-program-invocation/anchor/tests/litesvm.test.ts +++ b/basics/cross-program-invocation/anchor/tests/litesvm.test.ts @@ -1,152 +1,135 @@ import anchor from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; import { assert } from "chai"; import { LiteSVM } from "litesvm"; import HAND_IDL from "../target/idl/hand.json" with { type: "json" }; import LEVER_IDL from "../target/idl/lever.json" with { type: "json" }; describe("LiteSVM: CPI", () => { - const svm = new LiteSVM(); - const handProgramId = new PublicKey(HAND_IDL.address); - const leverProgramId = new PublicKey(LEVER_IDL.address); - - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(1000000000)); - - /** - * For serialization and deserialization of data - */ - const handCoder = new anchor.BorshCoder(HAND_IDL as anchor.Idl); - const leverCoder = new anchor.BorshCoder(LEVER_IDL as anchor.Idl); - - const handProgramPath = new URL("../target/deploy/hand.so", import.meta.url) - .pathname; - const leverProgramPath = new URL("../target/deploy/lever.so", import.meta.url) - .pathname; - svm.addProgramFromFile(handProgramId, handProgramPath); - svm.addProgramFromFile(leverProgramId, leverProgramPath); - - /** - * Generate a new keypair for the power account - */ - const powerAccount = new Keypair(); - - it("Initialize the lever!", () => { - /** - * Instruction data - * Create Transaction - * Send Transaction - */ - const data = leverCoder.instruction.encode("initialize", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: powerAccount.publicKey, isSigner: true, isWritable: true }, - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId: leverProgramId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer, powerAccount); - svm.sendTransaction(tx); - - /** - * Fetch account - * Check its required lamports - * Check it powerstatus - * */ - const minLamports = svm.minimumBalanceForRentExemption(BigInt(8 + 8)); - const powerAccountInfo = svm.getAccount(powerAccount.publicKey); - const powerStatus = leverCoder.accounts.decode( - "PowerStatus", - Buffer.from(powerAccountInfo.data), - ); - - assert(Number(minLamports) === powerAccountInfo.lamports); - assert(powerStatus.is_on === false); - }); - - it("Pull the lever!", () => { - /** - * Instruction data - * Create Transaction - * Send Transaction - */ - const data = handCoder.instruction.encode("pull_lever", { - name: "Jacob", - }); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: powerAccount.publicKey, isSigner: false, isWritable: true }, - { pubkey: leverProgramId, isSigner: false, isWritable: false }, - ], - programId: handProgramId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - - /** - * Fetch account - * Check its powerstatus = true - * */ - const powerAccountInfo = svm.getAccount(powerAccount.publicKey); - const powerStatus = leverCoder.accounts.decode( - "PowerStatus", - Buffer.from(powerAccountInfo.data), - ); - - assert(powerStatus.is_on === true); - }); - - it("Pull it again!", () => { - /** - * Instruction data - * Create Transaction - * Send Transaction - */ - const data = handCoder.instruction.encode("pull_lever", { - name: "sol-warrior", - }); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: powerAccount.publicKey, isSigner: false, isWritable: true }, - { pubkey: leverProgramId, isSigner: false, isWritable: false }, - ], - programId: handProgramId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - - /** - * Fetch account - * Check its powerstatus = false - * */ - const powerAccountInfo = svm.getAccount(powerAccount.publicKey); - const powerStatus = leverCoder.accounts.decode( - "PowerStatus", - Buffer.from(powerAccountInfo.data), - ); - - assert(powerStatus.is_on === false); - }); + const svm = new LiteSVM(); + const handProgramId = new PublicKey(HAND_IDL.address); + const leverProgramId = new PublicKey(LEVER_IDL.address); + + const payer = Keypair.generate(); + svm.airdrop(payer.publicKey, BigInt(1000000000)); + + /** + * For serialization and deserialization of data + */ + const handCoder = new anchor.BorshCoder(HAND_IDL as anchor.Idl); + const leverCoder = new anchor.BorshCoder(LEVER_IDL as anchor.Idl); + + const handProgramPath = new URL("../target/deploy/hand.so", import.meta.url).pathname; + const leverProgramPath = new URL("../target/deploy/lever.so", import.meta.url).pathname; + svm.addProgramFromFile(handProgramId, handProgramPath); + svm.addProgramFromFile(leverProgramId, leverProgramPath); + + /** + * Generate a new keypair for the power account + */ + const powerAccount = new Keypair(); + + it("Initialize the lever!", () => { + /** + * Instruction data + * Create Transaction + * Send Transaction + */ + const data = leverCoder.instruction.encode("initialize", {}); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: powerAccount.publicKey, isSigner: true, isWritable: true }, + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId: leverProgramId, + data, + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer, powerAccount); + svm.sendTransaction(tx); + + /** + * Fetch account + * Check its required lamports + * Check it powerstatus + * */ + const minLamports = svm.minimumBalanceForRentExemption(BigInt(8 + 8)); + const powerAccountInfo = svm.getAccount(powerAccount.publicKey); + const powerStatus = leverCoder.accounts.decode("PowerStatus", Buffer.from(powerAccountInfo.data)); + + assert(Number(minLamports) === powerAccountInfo.lamports); + assert(powerStatus.is_on === false); + }); + + it("Pull the lever!", () => { + /** + * Instruction data + * Create Transaction + * Send Transaction + */ + const data = handCoder.instruction.encode("pull_lever", { + name: "Jacob", + }); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: powerAccount.publicKey, isSigner: false, isWritable: true }, + { pubkey: leverProgramId, isSigner: false, isWritable: false }, + ], + programId: handProgramId, + data, + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + + /** + * Fetch account + * Check its powerstatus = true + * */ + const powerAccountInfo = svm.getAccount(powerAccount.publicKey); + const powerStatus = leverCoder.accounts.decode("PowerStatus", Buffer.from(powerAccountInfo.data)); + + assert(powerStatus.is_on === true); + }); + + it("Pull it again!", () => { + /** + * Instruction data + * Create Transaction + * Send Transaction + */ + const data = handCoder.instruction.encode("pull_lever", { + name: "sol-warrior", + }); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: powerAccount.publicKey, isSigner: false, isWritable: true }, + { pubkey: leverProgramId, isSigner: false, isWritable: false }, + ], + programId: handProgramId, + data, + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + + /** + * Fetch account + * Check its powerstatus = false + * */ + const powerAccountInfo = svm.getAccount(powerAccount.publicKey); + const powerStatus = leverCoder.accounts.decode("PowerStatus", Buffer.from(powerAccountInfo.data)); + + assert(powerStatus.is_on === false); + }); }); diff --git a/basics/cross-program-invocation/anchor/tests/test.ts b/basics/cross-program-invocation/anchor/tests/test.ts index d01c1c3ec..228593f81 100644 --- a/basics/cross-program-invocation/anchor/tests/test.ts +++ b/basics/cross-program-invocation/anchor/tests/test.ts @@ -5,78 +5,69 @@ import type { Hand } from "../target/types/hand.ts"; import type { Lever } from "../target/types/lever.ts"; describe("Anchor: CPI", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); - const hand = anchor.workspace.Hand as Program; - const lever = anchor.workspace.Lever as Program; + const hand = anchor.workspace.Hand as Program; + const lever = anchor.workspace.Lever as Program; - // Generate a new keypair for the power account - const powerAccount = new anchor.web3.Keypair(); + // Generate a new keypair for the power account + const powerAccount = new anchor.web3.Keypair(); - it("Initialize the lever!", async () => { - await lever.methods - .initialize() - .accounts({ - power: powerAccount.publicKey, - user: provider.wallet.publicKey, - }) - .signers([powerAccount]) - .rpc(); + it("Initialize the lever!", async () => { + await lever.methods + .initialize() + .accounts({ + power: powerAccount.publicKey, + user: provider.wallet.publicKey, + }) + .signers([powerAccount]) + .rpc(); - /** - * Fetch account - * Check its required lamports - * Check it powerstatus - * */ - const minLamports = - await provider.connection.getMinimumBalanceForRentExemption(8 + 8); - const powerStatus = await lever.account.powerStatus.fetch( - powerAccount.publicKey, - ); - const powerAccountInfo = await provider.connection.getAccountInfo( - powerAccount.publicKey, - ); + /** + * Fetch account + * Check its required lamports + * Check it powerstatus + * */ + const minLamports = await provider.connection.getMinimumBalanceForRentExemption(8 + 8); + const powerStatus = await lever.account.powerStatus.fetch(powerAccount.publicKey); + const powerAccountInfo = await provider.connection.getAccountInfo(powerAccount.publicKey); - assert(Number(minLamports) === powerAccountInfo.lamports); - assert(powerStatus.isOn === false); - }); + assert(Number(minLamports) === powerAccountInfo.lamports); + assert(powerStatus.isOn === false); + }); - it("Pull the lever!", async () => { - await hand.methods - .pullLever("Jacob") - .accounts({ - power: powerAccount.publicKey, - }) - .rpc(); + it("Pull the lever!", async () => { + await hand.methods + .pullLever("Jacob") + .accounts({ + power: powerAccount.publicKey, + }) + .rpc(); - /** - * Fetch account - * Check its powerstatus = true - * */ - const powerStatus = await lever.account.powerStatus.fetch( - powerAccount.publicKey, - ); + /** + * Fetch account + * Check its powerstatus = true + * */ + const powerStatus = await lever.account.powerStatus.fetch(powerAccount.publicKey); - assert(powerStatus.isOn === true); - }); + assert(powerStatus.isOn === true); + }); - it("Pull it again!", async () => { - await hand.methods - .pullLever("sol-warrior") - .accounts({ - power: powerAccount.publicKey, - }) - .rpc(); + it("Pull it again!", async () => { + await hand.methods + .pullLever("sol-warrior") + .accounts({ + power: powerAccount.publicKey, + }) + .rpc(); - /** - * Fetch account - * Check its powerstatus = false - * */ - const powerStatus = await lever.account.powerStatus.fetch( - powerAccount.publicKey, - ); + /** + * Fetch account + * Check its powerstatus = false + * */ + const powerStatus = await lever.account.powerStatus.fetch(powerAccount.publicKey); - assert(powerStatus.isOn === false); - }); + assert(powerStatus.isOn === false); + }); }); diff --git a/basics/cross-program-invocation/anchor/tsconfig.json b/basics/cross-program-invocation/anchor/tsconfig.json index fdf5c04de..395d18165 100644 --- a/basics/cross-program-invocation/anchor/tsconfig.json +++ b/basics/cross-program-invocation/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2020"], - "module": "nodenext", - "target": "es2020", - "esModuleInterop": true - } + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2020"], + "module": "nodenext", + "target": "es2020", + "esModuleInterop": true + } } diff --git a/basics/cross-program-invocation/native/programs/hand/Cargo.toml b/basics/cross-program-invocation/native/programs/hand/Cargo.toml index 26bc992a4..c74aab0f4 100644 --- a/basics/cross-program-invocation/native/programs/hand/Cargo.toml +++ b/basics/cross-program-invocation/native/programs/hand/Cargo.toml @@ -19,7 +19,7 @@ cross-program-invocatio-native-lever = { path = "../lever", features = ["cpi"] } crate-type = ["cdylib", "lib"] [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/cross-program-invocation/native/tests/test.ts b/basics/cross-program-invocation/native/tests/test.ts index efbca8062..c9dc4249b 100644 --- a/basics/cross-program-invocation/native/tests/test.ts +++ b/basics/cross-program-invocation/native/tests/test.ts @@ -1,19 +1,26 @@ -import { Buffer } from 'node:buffer'; -import { Connection, Keypair, SystemProgram, sendAndConfirmTransaction, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; +import { Buffer } from "node:buffer"; +import { + Connection, + Keypair, + SystemProgram, + sendAndConfirmTransaction, + Transaction, + TransactionInstruction, +} from "@solana/web3.js"; +import * as borsh from "borsh"; function createKeypairFromFile(path: string): Keypair { - return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require('node:fs').readFileSync(path, 'utf-8')))); + return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require("node:fs").readFileSync(path, "utf-8")))); } -describe('CPI Example', () => { - const connection = new Connection('http://localhost:8899', 'confirmed'); - const payer = createKeypairFromFile(`${require('node:os').homedir()}/.config/solana/id.json`); - const hand = createKeypairFromFile('./target/so/hand-keypair.json'); - const lever = createKeypairFromFile('./target/so/lever-keypair.json'); +describe("CPI Example", () => { + const connection = new Connection("http://localhost:8899", "confirmed"); + const payer = createKeypairFromFile(`${require("node:os").homedir()}/.config/solana/id.json`); + const hand = createKeypairFromFile("./target/so/hand-keypair.json"); + const lever = createKeypairFromFile("./target/so/lever-keypair.json"); - const PowerStatusSchema = { struct: { is_on: 'u8' } }; - const SetPowerStatusSchema = { struct: { name: 'string' } }; + const PowerStatusSchema = { struct: { is_on: "u8" } }; + const SetPowerStatusSchema = { struct: { name: "string" } }; function borshSerialize(schema: borsh.Schema, data: object): Buffer { return Buffer.from(borsh.serialize(schema, data)); @@ -21,7 +28,7 @@ describe('CPI Example', () => { const powerAccount = Keypair.generate(); - it('Initialize the lever!', async () => { + it("Initialize the lever!", async () => { const ix = new TransactionInstruction({ keys: [ { pubkey: powerAccount.publicKey, isSigner: true, isWritable: true }, @@ -35,27 +42,27 @@ describe('CPI Example', () => { await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, powerAccount]); }); - it('Pull the lever!', async () => { + it("Pull the lever!", async () => { const ix = new TransactionInstruction({ keys: [ { pubkey: powerAccount.publicKey, isSigner: false, isWritable: true }, { pubkey: lever.publicKey, isSigner: false, isWritable: false }, ], programId: hand.publicKey, - data: borshSerialize(SetPowerStatusSchema, { name: 'Chris' }), + data: borshSerialize(SetPowerStatusSchema, { name: "Chris" }), }); await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]); }); - it('Pull it again!', async () => { + it("Pull it again!", async () => { const ix = new TransactionInstruction({ keys: [ { pubkey: powerAccount.publicKey, isSigner: false, isWritable: true }, { pubkey: lever.publicKey, isSigner: false, isWritable: false }, ], programId: hand.publicKey, - data: borshSerialize(SetPowerStatusSchema, { name: 'Ashley' }), + data: borshSerialize(SetPowerStatusSchema, { name: "Ashley" }), }); await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]); diff --git a/basics/favorites/anchor/Anchor.toml b/basics/favorites/anchor/Anchor.toml index 97b3b5968..e748c486c 100644 --- a/basics/favorites/anchor/Anchor.toml +++ b/basics/favorites/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -favorites = "ww9C83noARSQVBnqmCUmaVdbJjmiwcV9j2LkXYMoUCV" - -# [registry] section removed — no longer used in Anchor 1.0 +favorites = "4wHiZQvMXQKaF1BbgN9Y9D5g1dZersK3J7mLGG5cUjEm" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/favorites/anchor/migrations/deploy.ts b/basics/favorites/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/basics/favorites/anchor/migrations/deploy.ts +++ b/basics/favorites/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/basics/favorites/anchor/package.json b/basics/favorites/anchor/package.json index 7cf70d1bb..95df8da6d 100644 --- a/basics/favorites/anchor/package.json +++ b/basics/favorites/anchor/package.json @@ -1,23 +1,23 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "license": "MIT", - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "license": "MIT", + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/favorites/anchor/pnpm-lock.yaml b/basics/favorites/anchor/pnpm-lock.yaml index d54575b8d..9adb9f5d3 100644 --- a/basics/favorites/anchor/pnpm-lock.yaml +++ b/basics/favorites/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -45,18 +45,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': @@ -768,16 +768,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -795,7 +795,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: diff --git a/basics/favorites/anchor/programs/favorites/Cargo.toml b/basics/favorites/anchor/programs/favorites/Cargo.toml index 10723e99c..cd3da05c2 100644 --- a/basics/favorites/anchor/programs/favorites/Cargo.toml +++ b/basics/favorites/anchor/programs/favorites/Cargo.toml @@ -20,7 +20,13 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = {version = "1.0.0-rc.5", features = ["init-if-needed"]} +anchor-lang = {version = "1.0.0", features = ["init-if-needed"]} + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/favorites/anchor/programs/favorites/src/lib.rs b/basics/favorites/anchor/programs/favorites/src/lib.rs index 670d65a70..dd8c3c4c5 100644 --- a/basics/favorites/anchor/programs/favorites/src/lib.rs +++ b/basics/favorites/anchor/programs/favorites/src/lib.rs @@ -1,7 +1,7 @@ use anchor_lang::prelude::*; // Our program's address! // This matches the key in the target/deploy directory -declare_id!("ww9C83noARSQVBnqmCUmaVdbJjmiwcV9j2LkXYMoUCV"); +declare_id!("4wHiZQvMXQKaF1BbgN9Y9D5g1dZersK3J7mLGG5cUjEm"); // Anchor programs always use 8 bits for the discriminator pub const ANCHOR_DISCRIMINATOR_SIZE: usize = 8; diff --git a/basics/favorites/anchor/programs/favorites/tests/test_favorites.rs b/basics/favorites/anchor/programs/favorites/tests/test_favorites.rs new file mode 100644 index 000000000..8a9cf7aec --- /dev/null +++ b/basics/favorites/anchor/programs/favorites/tests/test_favorites.rs @@ -0,0 +1,163 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +struct FavoritesData { + number: u64, + color: String, + hobbies: Vec, +} + +/// Manually deserialize the Favorites account data, skipping the 8-byte discriminator. +/// We can't use BorshDeserialize on the full account because init_if_needed allocates +/// more space than the serialized data occupies (padding for max_len strings/vecs). +fn read_favorites(svm: &LiteSVM, pda: &Pubkey) -> FavoritesData { + let account = svm.get_account(pda).unwrap(); + let data = &account.data[8..]; // skip discriminator + let mut offset = 0; + + // u64 number + let number = u64::from_le_bytes(data[offset..offset + 8].try_into().unwrap()); + offset += 8; + + // String color (4-byte length prefix + utf8 data) + let color_len = u32::from_le_bytes(data[offset..offset + 4].try_into().unwrap()) as usize; + offset += 4; + let color = String::from_utf8(data[offset..offset + color_len].to_vec()).unwrap(); + offset += color_len; + + // Vec hobbies (4-byte vec length + each string) + let hobbies_count = + u32::from_le_bytes(data[offset..offset + 4].try_into().unwrap()) as usize; + offset += 4; + let mut hobbies = Vec::with_capacity(hobbies_count); + for _ in 0..hobbies_count { + let hobby_len = + u32::from_le_bytes(data[offset..offset + 4].try_into().unwrap()) as usize; + offset += 4; + let hobby = String::from_utf8(data[offset..offset + hobby_len].to_vec()).unwrap(); + offset += hobby_len; + hobbies.push(hobby); + } + + FavoritesData { + number, + color, + hobbies, + } +} + +fn setup() -> (LiteSVM, Pubkey, solana_keypair::Keypair) { + let program_id = favorites::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/favorites.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +fn favorites_pda(program_id: &Pubkey, user: &Pubkey) -> Pubkey { + Pubkey::find_program_address(&[b"favorites", user.as_ref()], program_id).0 +} + +#[test] +fn test_set_favorites() { + let (mut svm, program_id, payer) = setup(); + let pda = favorites_pda(&program_id, &payer.pubkey()); + + let instruction = Instruction::new_with_bytes( + program_id, + &favorites::instruction::SetFavorites { + number: 23, + color: "purple".to_string(), + hobbies: vec![ + "skiing".to_string(), + "skydiving".to_string(), + "biking".to_string(), + ], + } + .data(), + favorites::accounts::SetFavorites { + user: payer.pubkey(), + favorites: pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![instruction], &[&payer], &payer.pubkey()) + .unwrap(); + + let data = read_favorites(&svm, &pda); + assert_eq!(data.number, 23); + assert_eq!(data.color, "purple"); + assert_eq!(data.hobbies, vec!["skiing", "skydiving", "biking"]); +} + +#[test] +fn test_update_favorites() { + let (mut svm, program_id, payer) = setup(); + let pda = favorites_pda(&program_id, &payer.pubkey()); + + // Set initial favorites + let instruction = Instruction::new_with_bytes( + program_id, + &favorites::instruction::SetFavorites { + number: 23, + color: "purple".to_string(), + hobbies: vec![ + "skiing".to_string(), + "skydiving".to_string(), + "biking".to_string(), + ], + } + .data(), + favorites::accounts::SetFavorites { + user: payer.pubkey(), + favorites: pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![instruction], &[&payer], &payer.pubkey()) + .unwrap(); + + // Update favorites with new hobbies + svm.expire_blockhash(); + let update_ix = Instruction::new_with_bytes( + program_id, + &favorites::instruction::SetFavorites { + number: 23, + color: "purple".to_string(), + hobbies: vec![ + "skiing".to_string(), + "skydiving".to_string(), + "biking".to_string(), + "swimming".to_string(), + ], + } + .data(), + favorites::accounts::SetFavorites { + user: payer.pubkey(), + favorites: pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![update_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + let data = read_favorites(&svm, &pda); + assert_eq!(data.number, 23); + assert_eq!(data.color, "purple"); + assert_eq!( + data.hobbies, + vec!["skiing", "skydiving", "biking", "swimming"] + ); +} diff --git a/basics/favorites/anchor/tests/litesvm.test.ts b/basics/favorites/anchor/tests/litesvm.test.ts index c3d7c031d..34fd39e18 100644 --- a/basics/favorites/anchor/tests/litesvm.test.ts +++ b/basics/favorites/anchor/tests/litesvm.test.ts @@ -1,143 +1,130 @@ import anchor from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; import { assert } from "chai"; import { LiteSVM } from "litesvm"; import IDL from "../target/idl/favorites.json" with { type: "json" }; describe("LiteSVM: Favorites", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(IDL.address); - const coder = new anchor.BorshCoder(IDL as anchor.Idl); //For serialization and deserialization - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(1000000000)); - - const programPath = new URL("../target/deploy/favorites.so", import.meta.url) - .pathname; - svm.addProgramFromFile(programId, programPath); - - const [favPdaAccount] = PublicKey.findProgramAddressSync( - [Buffer.from("favorites"), payer.publicKey.toBuffer()], - programId, - ); - /** - * Here's what we want to write to the blockchain - */ - const favoriteNumber = new anchor.BN(23); - const favoriteColor = "purple"; - const favoriteHobbies = ["skiing", "skydiving", "biking"]; - - it("Writes our favorites to the blockchain", () => { - const ixArgs = { - number: favoriteNumber, - color: favoriteColor, - hobbies: favoriteHobbies, - }; - - const data = coder.instruction.encode("set_favorites", ixArgs); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: favPdaAccount, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - - /** - * Fetch the account and check its favorites - */ - const favAccountInfo = svm.getAccount(favPdaAccount); - const favAccount = coder.accounts.decode( - "Favorites", - Buffer.from(favAccountInfo.data), - ); - - assert.equal(favAccount.number.toNumber(), favoriteNumber.toNumber()); - assert.equal(favAccount.color, favoriteColor); - assert.deepStrictEqual(favAccount.hobbies, favoriteHobbies); - }); - - it("Updates the favorites", () => { - const newFavoriteHobbies = ["coding", "reading", "biking", "swimming"]; - const ixArgs = { - number: favoriteNumber, - color: favoriteColor, - hobbies: newFavoriteHobbies, - }; - - const data = coder.instruction.encode("set_favorites", ixArgs); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: favPdaAccount, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - - /** - * Fetch the account and check its favorites - */ - const favAccountInfo = svm.getAccount(favPdaAccount); - const favAccount = coder.accounts.decode( - "Favorites", - Buffer.from(favAccountInfo.data), - ); - - assert.equal(favAccount.number.toNumber(), favoriteNumber.toNumber()); - assert.equal(favAccount.color, favoriteColor); - assert.deepStrictEqual(favAccount.hobbies, newFavoriteHobbies); - }); - - it("Rejects transactions from unauthorized signers", () => { - const newFavoriteHobbies = ["coding", "reading", "biking"]; - const someRandomGuy = Keypair.generate(); - - const ixArgs = { - number: favoriteNumber, - color: favoriteColor, - hobbies: newFavoriteHobbies, - }; - - const data = coder.instruction.encode("set_favorites", ixArgs); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: favPdaAccount, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - - assert.Throw(() => { - tx.sign(someRandomGuy); - svm.sendTransaction(tx); - }, "unknown signer"); - }); + const svm = new LiteSVM(); + const programId = new PublicKey(IDL.address); + const coder = new anchor.BorshCoder(IDL as anchor.Idl); //For serialization and deserialization + const payer = Keypair.generate(); + svm.airdrop(payer.publicKey, BigInt(1000000000)); + + const programPath = new URL("../target/deploy/favorites.so", import.meta.url).pathname; + svm.addProgramFromFile(programId, programPath); + + const [favPdaAccount] = PublicKey.findProgramAddressSync( + [Buffer.from("favorites"), payer.publicKey.toBuffer()], + programId, + ); + /** + * Here's what we want to write to the blockchain + */ + const favoriteNumber = new anchor.BN(23); + const favoriteColor = "purple"; + const favoriteHobbies = ["skiing", "skydiving", "biking"]; + + it("Writes our favorites to the blockchain", () => { + const ixArgs = { + number: favoriteNumber, + color: favoriteColor, + hobbies: favoriteHobbies, + }; + + const data = coder.instruction.encode("set_favorites", ixArgs); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: favPdaAccount, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + + /** + * Fetch the account and check its favorites + */ + const favAccountInfo = svm.getAccount(favPdaAccount); + const favAccount = coder.accounts.decode("Favorites", Buffer.from(favAccountInfo.data)); + + assert.equal(favAccount.number.toNumber(), favoriteNumber.toNumber()); + assert.equal(favAccount.color, favoriteColor); + assert.deepStrictEqual(favAccount.hobbies, favoriteHobbies); + }); + + it("Updates the favorites", () => { + const newFavoriteHobbies = ["coding", "reading", "biking", "swimming"]; + const ixArgs = { + number: favoriteNumber, + color: favoriteColor, + hobbies: newFavoriteHobbies, + }; + + const data = coder.instruction.encode("set_favorites", ixArgs); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: favPdaAccount, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + + /** + * Fetch the account and check its favorites + */ + const favAccountInfo = svm.getAccount(favPdaAccount); + const favAccount = coder.accounts.decode("Favorites", Buffer.from(favAccountInfo.data)); + + assert.equal(favAccount.number.toNumber(), favoriteNumber.toNumber()); + assert.equal(favAccount.color, favoriteColor); + assert.deepStrictEqual(favAccount.hobbies, newFavoriteHobbies); + }); + + it("Rejects transactions from unauthorized signers", () => { + const newFavoriteHobbies = ["coding", "reading", "biking"]; + const someRandomGuy = Keypair.generate(); + + const ixArgs = { + number: favoriteNumber, + color: favoriteColor, + hobbies: newFavoriteHobbies, + }; + + const data = coder.instruction.encode("set_favorites", ixArgs); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: favPdaAccount, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + + assert.Throw(() => { + tx.sign(someRandomGuy); + svm.sendTransaction(tx); + }, "unknown signer"); + }); }); diff --git a/basics/favorites/anchor/tests/test.ts b/basics/favorites/anchor/tests/test.ts index c39d43a6f..c77cfa258 100644 --- a/basics/favorites/anchor/tests/test.ts +++ b/basics/favorites/anchor/tests/test.ts @@ -5,83 +5,77 @@ import { assert } from "chai"; import type { Favorites } from "../target/types/favorites.ts"; describe("Anchor: Favorites", () => { - // Use the cluster and the keypair from Anchor.toml - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const web3 = anchor.web3; - // See https://github.com/coral-xyz/anchor/issues/3122 - const user = (provider.wallet as anchor.Wallet).payer; - const someRandomGuy = anchor.web3.Keypair.generate(); - const program = anchor.workspace.Favorites as Program; + // Use the cluster and the keypair from Anchor.toml + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const web3 = anchor.web3; + // See https://github.com/coral-xyz/anchor/issues/3122 + const user = (provider.wallet as anchor.Wallet).payer; + const someRandomGuy = anchor.web3.Keypair.generate(); + const program = anchor.workspace.Favorites as Program; - // Here's what we want to write to the blockchain - const favoriteNumber = new BN(23); - const favoriteColor = "purple"; - const favoriteHobbies = ["skiing", "skydiving", "biking"]; + // Here's what we want to write to the blockchain + const favoriteNumber = new BN(23); + const favoriteColor = "purple"; + const favoriteHobbies = ["skiing", "skydiving", "biking"]; - // We don't need to airdrop if we're using the local cluster - // because the local cluster gives us 85 billion dollars worth of SOL - before(async () => { - const balance = await provider.connection.getBalance(user.publicKey); - const balanceInSOL = balance / web3.LAMPORTS_PER_SOL; - const formattedBalance = new Intl.NumberFormat().format(balanceInSOL); - console.log(`Balance: ${formattedBalance} SOL`); - }); + // We don't need to airdrop if we're using the local cluster + // because the local cluster gives us 85 billion dollars worth of SOL + before(async () => { + const balance = await provider.connection.getBalance(user.publicKey); + const balanceInSOL = balance / web3.LAMPORTS_PER_SOL; + const formattedBalance = new Intl.NumberFormat().format(balanceInSOL); + console.log(`Balance: ${formattedBalance} SOL`); + }); - it("Writes our favorites to the blockchain", async () => { - await program.methods - // set_favourites in Rust becomes setFavorites in TypeScript - .setFavorites(favoriteNumber, favoriteColor, favoriteHobbies) - // Sign the transaction - .signers([user]) - // Send the transaction to the cluster or RPC - .rpc(); + it("Writes our favorites to the blockchain", async () => { + await program.methods + // set_favourites in Rust becomes setFavorites in TypeScript + .setFavorites(favoriteNumber, favoriteColor, favoriteHobbies) + // Sign the transaction + .signers([user]) + // Send the transaction to the cluster or RPC + .rpc(); - // Find the PDA for the user's favorites - const favoritesPdaAndBump = web3.PublicKey.findProgramAddressSync( - [Buffer.from("favorites"), user.publicKey.toBuffer()], - program.programId, - ); - const favoritesPda = favoritesPdaAndBump[0]; - const dataFromPda = await program.account.favorites.fetch(favoritesPda); - // And make sure it matches! - assert.equal(dataFromPda.color, favoriteColor); - // A little extra work to make sure the BNs are equal - assert.equal(dataFromPda.number.toString(), favoriteNumber.toString()); - // And check the hobbies too - assert.deepEqual(dataFromPda.hobbies, favoriteHobbies); - }); + // Find the PDA for the user's favorites + const favoritesPdaAndBump = web3.PublicKey.findProgramAddressSync( + [Buffer.from("favorites"), user.publicKey.toBuffer()], + program.programId, + ); + const favoritesPda = favoritesPdaAndBump[0]; + const dataFromPda = await program.account.favorites.fetch(favoritesPda); + // And make sure it matches! + assert.equal(dataFromPda.color, favoriteColor); + // A little extra work to make sure the BNs are equal + assert.equal(dataFromPda.number.toString(), favoriteNumber.toString()); + // And check the hobbies too + assert.deepEqual(dataFromPda.hobbies, favoriteHobbies); + }); - it("Updates the favorites", async () => { - const newFavoriteHobbies = ["skiing", "skydiving", "biking", "swimming"]; + it("Updates the favorites", async () => { + const newFavoriteHobbies = ["skiing", "skydiving", "biking", "swimming"]; - await program.methods - .setFavorites(favoriteNumber, favoriteColor, newFavoriteHobbies) - .signers([user]) - .rpc(); + await program.methods.setFavorites(favoriteNumber, favoriteColor, newFavoriteHobbies).signers([user]).rpc(); - // Find the PDA for the user's favorites - const favoritesPdaAndBump = web3.PublicKey.findProgramAddressSync( - [Buffer.from("favorites"), user.publicKey.toBuffer()], - program.programId, - ); - const favoritesPda = favoritesPdaAndBump[0]; - const dataFromPda = await program.account.favorites.fetch(favoritesPda); + // Find the PDA for the user's favorites + const favoritesPdaAndBump = web3.PublicKey.findProgramAddressSync( + [Buffer.from("favorites"), user.publicKey.toBuffer()], + program.programId, + ); + const favoritesPda = favoritesPdaAndBump[0]; + const dataFromPda = await program.account.favorites.fetch(favoritesPda); - assert.equal(dataFromPda.color, favoriteColor); - assert.equal(dataFromPda.number.toString(), favoriteNumber.toString()); - assert.deepEqual(dataFromPda.hobbies, newFavoriteHobbies); - }); + assert.equal(dataFromPda.color, favoriteColor); + assert.equal(dataFromPda.number.toString(), favoriteNumber.toString()); + assert.deepEqual(dataFromPda.hobbies, newFavoriteHobbies); + }); - it("Rejects transactions from unauthorized signers", async () => { - try { - await program.methods - .setFavorites(favoriteNumber, favoriteColor, favoriteHobbies) - .signers([someRandomGuy]) - .rpc(); - assert.fail("Expected unauthorized signer error"); - } catch (err) { - assert.include((err as Error).message, "unknown signer"); - } - }); + it("Rejects transactions from unauthorized signers", async () => { + try { + await program.methods.setFavorites(favoriteNumber, favoriteColor, favoriteHobbies).signers([someRandomGuy]).rpc(); + assert.fail("Expected unauthorized signer error"); + } catch (err) { + assert.include((err as Error).message, "unknown signer"); + } + }); }); diff --git a/basics/favorites/anchor/tsconfig.json b/basics/favorites/anchor/tsconfig.json index fdf5c04de..395d18165 100644 --- a/basics/favorites/anchor/tsconfig.json +++ b/basics/favorites/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2020"], - "module": "nodenext", - "target": "es2020", - "esModuleInterop": true - } + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2020"], + "module": "nodenext", + "target": "es2020", + "esModuleInterop": true + } } diff --git a/basics/favorites/native/program/Cargo.toml b/basics/favorites/native/program/Cargo.toml index fab1cd066..416af7197 100644 --- a/basics/favorites/native/program/Cargo.toml +++ b/basics/favorites/native/program/Cargo.toml @@ -20,7 +20,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/favorites/native/tests/test.ts b/basics/favorites/native/tests/test.ts index 0027bb7bb..13e5e5b34 100644 --- a/basics/favorites/native/tests/test.ts +++ b/basics/favorites/native/tests/test.ts @@ -1,6 +1,6 @@ import { - Blockhash, - Keypair, + type Blockhash, + type Keypair, PublicKey, SystemProgram, Transaction, @@ -10,7 +10,7 @@ import { BN } from "bn.js"; import * as borsh from "borsh"; import { assert, expect } from "chai"; import { describe, test } from "mocha"; -import { BanksClient, ProgramTestContext, start } from "solana-bankrun"; +import { type BanksClient, type ProgramTestContext, start } from "solana-bankrun"; const MyInstruction = { CreateFav: 0, @@ -103,9 +103,7 @@ describe("Favorites Solana Native", () => { console.log("Deserialized data:", favoritesData); - expect(new BN(favoritesData.number as any, "le").toNumber()).to.equal( - favData.number, - ); + expect(new BN(favoritesData.number as Buffer, "le").toNumber()).to.equal(favData.number); expect(favoritesData.color).to.equal(favData.color); expect(favoritesData.hobbies).to.deep.equal(favData.hobbies); }); diff --git a/basics/favorites/pinocchio/program/Cargo.toml b/basics/favorites/pinocchio/program/Cargo.toml index 576a8c916..2842e5f8c 100644 --- a/basics/favorites/pinocchio/program/Cargo.toml +++ b/basics/favorites/pinocchio/program/Cargo.toml @@ -21,7 +21,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/favorites/pinocchio/tests/test.ts b/basics/favorites/pinocchio/tests/test.ts index e6d02ff24..f63e2f8bb 100644 --- a/basics/favorites/pinocchio/tests/test.ts +++ b/basics/favorites/pinocchio/tests/test.ts @@ -1,16 +1,4 @@ -import { - Blockhash, - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; -import { BN } from "bn.js"; -import * as borsh from "borsh"; -import { assert, expect } from "chai"; -import { describe, test } from "mocha"; -import { BanksClient, ProgramTestContext, start } from "solana-bankrun"; +import { describe } from "mocha"; describe("Favorites Solana Pinocchio", () => { console.log("Favorites Solana Pinocchio"); diff --git a/basics/hello-solana/anchor/Anchor.toml b/basics/hello-solana/anchor/Anchor.toml index 7ac88bd13..7716a75a1 100644 --- a/basics/hello-solana/anchor/Anchor.toml +++ b/basics/hello-solana/anchor/Anchor.toml @@ -2,17 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false [programs.localnet] -hello_solana = "2phbC62wekpw95XuBk4i1KX4uA8zBUWmYbiTMhicSuBV" - -# [registry] section removed — no longer used in Anchor 1.0 +hello_solana = "52rNd2KDuqHaxs2vEFfEjH2zwKScA2B9AyW8F2fAcca8" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/hello-solana/anchor/package.json b/basics/hello-solana/anchor/package.json deleted file mode 100644 index 0696e9344..000000000 --- a/basics/hello-solana/anchor/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } -} diff --git a/basics/hello-solana/anchor/pnpm-lock.yaml b/basics/hello-solana/anchor/pnpm-lock.yaml deleted file mode 100644 index 685c53440..000000000 --- a/basics/hello-solana/anchor/pnpm-lock.yaml +++ /dev/null @@ -1,1466 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/web3.js': - specifier: ^1.98.4 - version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - litesvm: - specifier: ^0.4.0 - version: 0.4.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - devDependencies: - '@types/bn.js': - specifier: ^5.1.0 - version: 5.1.5 - '@types/chai': - specifier: ^4.3.0 - version: 4.3.16 - '@types/mocha': - specifier: ^9.0.0 - version: 9.1.1 - chai: - specifier: ^4.3.4 - version: 4.4.1 - mocha: - specifier: ^9.0.3 - version: 9.2.2 - ts-mocha: - specifier: ^10.0.0 - version: 10.0.0(mocha@9.2.2) - typescript: - specifier: ^5.3.3 - version: 5.9.3 - -packages: - - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} - engines: {node: '>=10'} - peerDependencies: - '@solana/web3.js': ^1.69.0 - - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} - engines: {node: '>=17'} - - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} - engines: {node: '>=10'} - - '@babel/runtime@7.25.0': - resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==} - engines: {node: '>=6.9.0'} - - '@noble/curves@1.4.2': - resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} - - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - - '@noble/hashes@1.8.0': - resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} - engines: {node: ^14.21.3 || >=16} - - '@solana/buffer-layout@4.0.1': - resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} - engines: {node: '>=5.10'} - - '@solana/codecs-core@2.3.0': - resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==} - engines: {node: '>=20.18.0'} - peerDependencies: - typescript: '>=5.3.3' - - '@solana/codecs-numbers@2.3.0': - resolution: {integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==} - engines: {node: '>=20.18.0'} - peerDependencies: - typescript: '>=5.3.3' - - '@solana/errors@2.3.0': - resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==} - engines: {node: '>=20.18.0'} - hasBin: true - peerDependencies: - typescript: '>=5.3.3' - - '@solana/web3.js@1.98.4': - resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==} - - '@swc/helpers@0.5.12': - resolution: {integrity: sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==} - - '@types/bn.js@5.1.5': - resolution: {integrity: sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==} - - '@types/chai@4.3.16': - resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} - - '@types/connect@3.4.38': - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - - '@types/mocha@9.1.1': - resolution: {integrity: sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==} - - '@types/node@12.20.55': - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - - '@types/node@20.12.11': - resolution: {integrity: sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==} - - '@types/uuid@8.3.4': - resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} - - '@types/ws@7.4.7': - resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} - - '@types/ws@8.5.12': - resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} - - '@ungap/promise-all-settled@1.1.2': - resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} - - JSONStream@1.3.5: - resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} - hasBin: true - - agentkeepalive@4.5.0: - resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} - engines: {node: '>= 8.0.0'} - - ansi-colors@4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} - engines: {node: '>=6'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base-x@3.0.9: - resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - bn.js@5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - - bn.js@5.2.2: - resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} - - borsh@0.7.0: - resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - - browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - - bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - buffer-layout@1.2.2: - resolution: {integrity: sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==} - engines: {node: '>=4.5'} - - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - bufferutil@4.0.8: - resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} - engines: {node: '>=6.14.2'} - - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chalk@5.6.2: - resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - - chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - commander@14.0.2: - resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} - engines: {node: '>=20'} - - commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - cross-fetch@3.2.0: - resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} - - debug@4.3.3: - resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - - deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} - - delay@5.0.0: - resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} - engines: {node: '>=10'} - - diff@3.5.0: - resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} - engines: {node: '>=0.3.1'} - - diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - es6-promise@4.2.8: - resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} - - es6-promisify@5.0.0: - resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - - eyes@0.1.8: - resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} - engines: {node: '> 0.1.90'} - - fast-stable-stringify@1.0.0: - resolution: {integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==} - - fastestsmallesttextencoderdecoder@1.0.22: - resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} - - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob@7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} - - growl@1.10.5: - resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==} - engines: {node: '>=4.x'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - isomorphic-ws@4.0.1: - resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} - peerDependencies: - ws: '*' - - jayson@4.1.1: - resolution: {integrity: sha512-5ZWm4Q/0DHPyeMfAsrwViwUS2DMVsQgWh8bEEIVTkfb3DzHZ2L3G5WUnF+AKmGjjM9r1uAv73SaqC1/U4RL45w==} - engines: {node: '>=8'} - hasBin: true - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - - json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - - jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - - litesvm-darwin-arm64@0.4.0: - resolution: {integrity: sha512-LN6iZcUQ6Xi5KO/7yJBYSALjjDCI/s/s2PgV3BqM4dpeBaLz+fXX/+qgMcBgpEVgEdEmhelux+WtAMkbEzJfrA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - litesvm-darwin-x64@0.4.0: - resolution: {integrity: sha512-3ltogKQdle8LbakVqoB6plxaNwp6Vb3tnkqa3G5mAvvZNorB2iumThDaTZ381Knl69t566LZm+g/VDZwYfsfhA==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] - - litesvm-linux-arm64-gnu@0.4.0: - resolution: {integrity: sha512-SWlcRUqkXCMgLoDX/Wqr/S1lff+ggVI9f0YrRJMraxtEyApxutAoW2AWw4tvo6DsEgNwjxgsZOAwnE6bQBv8CA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - litesvm-linux-arm64-musl@0.4.0: - resolution: {integrity: sha512-YMMqwEWJUSWwL0Rwp8dFwl3jvgNU21eI7Qc+BpH9u2yeIRYQTn3rNGDnsK8v3QIZPHQdMo7NrPhzk4XoB1aKPg==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [musl] - - litesvm-linux-x64-gnu@0.4.0: - resolution: {integrity: sha512-brZ3tFABDVQEYCgci7AO8iVYLw10UXVo97/lpTy75bTzNoqkggg8wFQOrbgCdb9NRwt06Y4Zf8cpIZAoDQq2mw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [glibc] - - litesvm-linux-x64-musl@0.4.0: - resolution: {integrity: sha512-D98qdIOuWg4fOewIIiH1D23AtM4I7/3vLKXIL8uQz06D5ev5fsBzNp2gM7libAywTkCYy/u666xgD6PsWhrTaw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [musl] - - litesvm@0.4.0: - resolution: {integrity: sha512-ySr5mB2ap4SzJpmVR2I5+gjzTH8NJbkg7DYPormzA2U9F4LhfvTTrD17X/k5N3Bn4b5Db6/CwSyX2qc0HrJtNA==} - engines: {node: '>= 20'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@4.2.1: - resolution: {integrity: sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==} - engines: {node: '>=10'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - mocha@9.2.2: - resolution: {integrity: sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==} - engines: {node: '>= 12.0.0'} - hasBin: true - - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.1: - resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - - node-gyp-build@4.8.1: - resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} - hasBin: true - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - pako@2.1.0: - resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - rpc-websockets@9.0.2: - resolution: {integrity: sha512-YzggvfItxMY3Lwuax5rC18inhbjJv9Py7JXRHxTIi94JOLrqBsSsUUc5bbl5W6c11tXhdfpDPK0KzBhoGe8jjw==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - serialize-javascript@6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} - - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - superstruct@0.15.5: - resolution: {integrity: sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==} - - superstruct@2.0.2: - resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} - engines: {node: '>=14.0.0'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - text-encoding-utf-8@1.0.2: - resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} - - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - toml@3.0.0: - resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} - - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - ts-mocha@10.0.0: - resolution: {integrity: sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw==} - engines: {node: '>= 6.X.X'} - hasBin: true - peerDependencies: - mocha: ^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X - - ts-node@7.0.1: - resolution: {integrity: sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==} - engines: {node: '>=4.2.0'} - hasBin: true - - tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - utf-8-validate@5.0.10: - resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} - engines: {node: '>=6.14.2'} - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - workerpool@6.2.0: - resolution: {integrity: sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yargs-parser@20.2.4: - resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} - engines: {node: '>=10'} - - yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} - - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - - yn@2.0.0: - resolution: {integrity: sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==} - engines: {node: '>=4'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': - dependencies: - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - bn.js: 5.2.2 - buffer-layout: 1.2.2 - - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 - '@noble/hashes': 1.8.0 - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - bn.js: 5.2.2 - bs58: 4.0.1 - buffer-layout: 1.2.2 - camelcase: 6.3.0 - cross-fetch: 3.2.0 - eventemitter3: 4.0.7 - pako: 2.1.0 - superstruct: 0.15.5 - toml: 3.0.0 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - '@anchor-lang/errors@1.0.0-rc.5': {} - - '@babel/runtime@7.25.0': - dependencies: - regenerator-runtime: 0.14.1 - - '@noble/curves@1.4.2': - dependencies: - '@noble/hashes': 1.4.0 - - '@noble/hashes@1.4.0': {} - - '@noble/hashes@1.8.0': {} - - '@solana/buffer-layout@4.0.1': - dependencies: - buffer: 6.0.3 - - '@solana/codecs-core@2.3.0(typescript@5.9.3)': - dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - - '@solana/codecs-numbers@2.3.0(typescript@5.9.3)': - dependencies: - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - - '@solana/errors@2.3.0(typescript@5.9.3)': - dependencies: - chalk: 5.6.2 - commander: 14.0.2 - typescript: 5.9.3 - - '@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@babel/runtime': 7.25.0 - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@solana/buffer-layout': 4.0.1 - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) - agentkeepalive: 4.5.0 - bn.js: 5.2.1 - borsh: 0.7.0 - bs58: 4.0.1 - buffer: 6.0.3 - fast-stable-stringify: 1.0.0 - jayson: 4.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) - node-fetch: 2.7.0 - rpc-websockets: 9.0.2 - superstruct: 2.0.2 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - '@swc/helpers@0.5.12': - dependencies: - tslib: 2.6.2 - - '@types/bn.js@5.1.5': - dependencies: - '@types/node': 20.12.11 - - '@types/chai@4.3.16': {} - - '@types/connect@3.4.38': - dependencies: - '@types/node': 20.12.11 - - '@types/json5@0.0.29': - optional: true - - '@types/mocha@9.1.1': {} - - '@types/node@12.20.55': {} - - '@types/node@20.12.11': - dependencies: - undici-types: 5.26.5 - - '@types/uuid@8.3.4': {} - - '@types/ws@7.4.7': - dependencies: - '@types/node': 20.12.11 - - '@types/ws@8.5.12': - dependencies: - '@types/node': 20.12.11 - - '@ungap/promise-all-settled@1.1.2': {} - - JSONStream@1.3.5: - dependencies: - jsonparse: 1.3.1 - through: 2.3.8 - - agentkeepalive@4.5.0: - dependencies: - humanize-ms: 1.2.1 - - ansi-colors@4.1.1: {} - - ansi-regex@5.0.1: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - argparse@2.0.1: {} - - arrify@1.0.1: {} - - assertion-error@1.1.0: {} - - balanced-match@1.0.2: {} - - base-x@3.0.9: - dependencies: - safe-buffer: 5.2.1 - - base64-js@1.5.1: {} - - binary-extensions@2.3.0: {} - - bn.js@5.2.1: {} - - bn.js@5.2.2: {} - - borsh@0.7.0: - dependencies: - bn.js: 5.2.1 - bs58: 4.0.1 - text-encoding-utf-8: 1.0.2 - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - braces@3.0.2: - dependencies: - fill-range: 7.0.1 - - browser-stdout@1.3.1: {} - - bs58@4.0.1: - dependencies: - base-x: 3.0.9 - - buffer-from@1.1.2: {} - - buffer-layout@1.2.2: {} - - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - bufferutil@4.0.8: - dependencies: - node-gyp-build: 4.8.1 - optional: true - - camelcase@6.3.0: {} - - chai@4.4.1: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.3 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.0.8 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chalk@5.6.2: {} - - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 - - chokidar@3.5.3: - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - commander@14.0.2: {} - - commander@2.20.3: {} - - concat-map@0.0.1: {} - - cross-fetch@3.2.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - debug@4.3.3(supports-color@8.1.1): - dependencies: - ms: 2.1.2 - optionalDependencies: - supports-color: 8.1.1 - - decamelize@4.0.0: {} - - deep-eql@4.1.3: - dependencies: - type-detect: 4.0.8 - - delay@5.0.0: {} - - diff@3.5.0: {} - - diff@5.0.0: {} - - emoji-regex@8.0.0: {} - - es6-promise@4.2.8: {} - - es6-promisify@5.0.0: - dependencies: - es6-promise: 4.2.8 - - escalade@3.1.2: {} - - escape-string-regexp@4.0.0: {} - - eventemitter3@4.0.7: {} - - eventemitter3@5.0.1: {} - - eyes@0.1.8: {} - - fast-stable-stringify@1.0.0: {} - - fastestsmallesttextencoderdecoder@1.0.22: {} - - fill-range@7.0.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat@5.0.2: {} - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - get-caller-file@2.0.5: {} - - get-func-name@2.0.2: {} - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - growl@1.10.5: {} - - has-flag@4.0.0: {} - - he@1.2.0: {} - - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - - ieee754@1.2.1: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - is-plain-obj@2.1.0: {} - - is-unicode-supported@0.1.0: {} - - isexe@2.0.0: {} - - isomorphic-ws@4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)): - dependencies: - ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) - - jayson@4.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10): - dependencies: - '@types/connect': 3.4.38 - '@types/node': 12.20.55 - '@types/ws': 7.4.7 - JSONStream: 1.3.5 - commander: 2.20.3 - delay: 5.0.0 - es6-promisify: 5.0.0 - eyes: 0.1.8 - isomorphic-ws: 4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - json-stringify-safe: 5.0.1 - uuid: 8.3.2 - ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - json-stringify-safe@5.0.1: {} - - json5@1.0.2: - dependencies: - minimist: 1.2.8 - optional: true - - jsonparse@1.3.1: {} - - litesvm-darwin-arm64@0.4.0: - optional: true - - litesvm-darwin-x64@0.4.0: - optional: true - - litesvm-linux-arm64-gnu@0.4.0: - optional: true - - litesvm-linux-arm64-musl@0.4.0: - optional: true - - litesvm-linux-x64-gnu@0.4.0: - optional: true - - litesvm-linux-x64-musl@0.4.0: - optional: true - - litesvm@0.4.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10): - dependencies: - '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) - fastestsmallesttextencoderdecoder: 1.0.22 - optionalDependencies: - litesvm-darwin-arm64: 0.4.0 - litesvm-darwin-x64: 0.4.0 - litesvm-linux-arm64-gnu: 0.4.0 - litesvm-linux-arm64-musl: 0.4.0 - litesvm-linux-x64-gnu: 0.4.0 - litesvm-linux-x64-musl: 0.4.0 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - - make-error@1.3.6: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@4.2.1: - dependencies: - brace-expansion: 1.1.11 - - minimist@1.2.8: {} - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - mocha@9.2.2: - dependencies: - '@ungap/promise-all-settled': 1.1.2 - ansi-colors: 4.1.1 - browser-stdout: 1.3.1 - chokidar: 3.5.3 - debug: 4.3.3(supports-color@8.1.1) - diff: 5.0.0 - escape-string-regexp: 4.0.0 - find-up: 5.0.0 - glob: 7.2.0 - growl: 1.10.5 - he: 1.2.0 - js-yaml: 4.1.0 - log-symbols: 4.1.0 - minimatch: 4.2.1 - ms: 2.1.3 - nanoid: 3.3.1 - serialize-javascript: 6.0.0 - strip-json-comments: 3.1.1 - supports-color: 8.1.1 - which: 2.0.2 - workerpool: 6.2.0 - yargs: 16.2.0 - yargs-parser: 20.2.4 - yargs-unparser: 2.0.0 - - ms@2.1.2: {} - - ms@2.1.3: {} - - nanoid@3.3.1: {} - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - - node-gyp-build@4.8.1: - optional: true - - normalize-path@3.0.0: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - pako@2.1.0: {} - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - pathval@1.1.1: {} - - picomatch@2.3.1: {} - - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - regenerator-runtime@0.14.1: {} - - require-directory@2.1.1: {} - - rpc-websockets@9.0.2: - dependencies: - '@swc/helpers': 0.5.12 - '@types/uuid': 8.3.4 - '@types/ws': 8.5.12 - buffer: 6.0.3 - eventemitter3: 5.0.1 - uuid: 8.3.2 - ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - safe-buffer@5.2.1: {} - - serialize-javascript@6.0.0: - dependencies: - randombytes: 2.1.0 - - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-bom@3.0.0: - optional: true - - strip-json-comments@3.1.1: {} - - superstruct@0.15.5: {} - - superstruct@2.0.2: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - text-encoding-utf-8@1.0.2: {} - - through@2.3.8: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - toml@3.0.0: {} - - tr46@0.0.3: {} - - ts-mocha@10.0.0(mocha@9.2.2): - dependencies: - mocha: 9.2.2 - ts-node: 7.0.1 - optionalDependencies: - tsconfig-paths: 3.15.0 - - ts-node@7.0.1: - dependencies: - arrify: 1.0.1 - buffer-from: 1.1.2 - diff: 3.5.0 - make-error: 1.3.6 - minimist: 1.2.8 - mkdirp: 0.5.6 - source-map-support: 0.5.21 - yn: 2.0.0 - - tsconfig-paths@3.15.0: - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - optional: true - - tslib@2.6.2: {} - - type-detect@4.0.8: {} - - typescript@5.9.3: {} - - undici-types@5.26.5: {} - - utf-8-validate@5.0.10: - dependencies: - node-gyp-build: 4.8.1 - optional: true - - uuid@8.3.2: {} - - webidl-conversions@3.0.1: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - workerpool@6.2.0: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrappy@1.0.2: {} - - ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - - y18n@5.0.8: {} - - yargs-parser@20.2.4: {} - - yargs-unparser@2.0.0: - dependencies: - camelcase: 6.3.0 - decamelize: 4.0.0 - flat: 5.0.2 - is-plain-obj: 2.1.0 - - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.4 - - yn@2.0.0: {} - - yocto-queue@0.1.0: {} diff --git a/basics/hello-solana/anchor/programs/hello-solana/Cargo.toml b/basics/hello-solana/anchor/programs/hello-solana/Cargo.toml index 455794ab9..9cadce60d 100644 --- a/basics/hello-solana/anchor/programs/hello-solana/Cargo.toml +++ b/basics/hello-solana/anchor/programs/hello-solana/Cargo.toml @@ -20,8 +20,12 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/hello-solana/anchor/programs/hello-solana/src/lib.rs b/basics/hello-solana/anchor/programs/hello-solana/src/lib.rs index d714080f3..ff0d0d25a 100644 --- a/basics/hello-solana/anchor/programs/hello-solana/src/lib.rs +++ b/basics/hello-solana/anchor/programs/hello-solana/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("2phbC62wekpw95XuBk4i1KX4uA8zBUWmYbiTMhicSuBV"); +declare_id!("52rNd2KDuqHaxs2vEFfEjH2zwKScA2B9AyW8F2fAcca8"); #[program] pub mod hello_solana { diff --git a/basics/hello-solana/anchor/programs/hello-solana/tests/test_hello.rs b/basics/hello-solana/anchor/programs/hello-solana/tests/test_hello.rs new file mode 100644 index 000000000..815d051a0 --- /dev/null +++ b/basics/hello-solana/anchor/programs/hello-solana/tests/test_hello.rs @@ -0,0 +1,24 @@ +use { + anchor_lang::{solana_program::instruction::Instruction, InstructionData, ToAccountMetas}, + litesvm::LiteSVM, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +#[test] +fn test_say_hello() { + let program_id = hello_solana::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/hello_solana.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 1_000_000_000).unwrap(); + + let instruction = Instruction::new_with_bytes( + program_id, + &hello_solana::instruction::Hello {}.data(), + hello_solana::accounts::Hello {}.to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![instruction], &[&payer], &payer.pubkey()) + .unwrap(); +} diff --git a/basics/hello-solana/anchor/tests/litesvm.test.ts b/basics/hello-solana/anchor/tests/litesvm.test.ts deleted file mode 100644 index 30f9e5b74..000000000 --- a/basics/hello-solana/anchor/tests/litesvm.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import anchor from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; -import { LiteSVM } from "litesvm"; -import IDL from "../target/idl/hello_solana.json" with { type: "json" }; - -describe("LiteSVM: hello-solana", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(IDL.address); - /** - * Creates a coder to easily build and encode program instructions based on the IDL. - */ - const coder = new anchor.BorshCoder(IDL as anchor.Idl); - - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(1000000000)); - - /** - * Load the hello_solana program binary into the LiteSVM instance - * for local testing and simulation. - */ - const programPath = new URL( - "../target/deploy/hello_solana.so", - import.meta.url, - ).pathname; - svm.addProgramFromFile(programId, programPath); - - it("Say hello!", () => { - /** - * Create an instruction for the 'hello' method using the Anchor coder. - * No arguments are needed for this instruction so i give `{}`. - */ - const data = coder.instruction.encode("hello", {}); - - /** - * Build and sign a transaction to call the 'hello' instruction - * on the hello_solana program with LiteSVM. - */ - const ix = new TransactionInstruction({ - keys: [], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - }); -}); diff --git a/basics/hello-solana/anchor/tests/test.ts b/basics/hello-solana/anchor/tests/test.ts deleted file mode 100644 index 18f4ab831..000000000 --- a/basics/hello-solana/anchor/tests/test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as anchor from "@anchor-lang/core"; -import type { HelloSolana } from "../target/types/hello_solana.ts"; - -describe("Anchor: hello-solana", () => { - // Configure the Anchor provider & load the program IDL - // The IDL gives you a typescript module - // - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const program = anchor.workspace.HelloSolana as anchor.Program; - - it("Say hello!", async () => { - // Just run Anchor's IDL method to build a transaction! - // - await program.methods.hello().accounts({}).rpc(); - }); -}); diff --git a/basics/hello-solana/anchor/tsconfig.json b/basics/hello-solana/anchor/tsconfig.json deleted file mode 100644 index fdf5c04de..000000000 --- a/basics/hello-solana/anchor/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2020"], - "module": "nodenext", - "target": "es2020", - "esModuleInterop": true - } -} diff --git a/basics/hello-solana/native/program/Cargo.toml b/basics/hello-solana/native/program/Cargo.toml index 6467e0684..a51e82ffa 100644 --- a/basics/hello-solana/native/program/Cargo.toml +++ b/basics/hello-solana/native/program/Cargo.toml @@ -17,7 +17,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/hello-solana/native/tests/index.test.ts b/basics/hello-solana/native/tests/index.test.ts index ec7daa61e..1c0c85b31 100644 --- a/basics/hello-solana/native/tests/index.test.ts +++ b/basics/hello-solana/native/tests/index.test.ts @@ -1,16 +1,16 @@ -import { describe, test } from 'node:test'; -import { PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js'; -import { assert } from 'chai'; -import { start } from 'solana-bankrun'; +import { describe, test } from "node:test"; +import { PublicKey, Transaction, TransactionInstruction } from "@solana/web3.js"; +import { assert } from "chai"; +import { start } from "solana-bankrun"; -describe('hello-solana', async () => { +describe("hello-solana", async () => { // load program in solana-bankrun const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'hello_solana_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "hello_solana_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; - test('Say hello!', async () => { + test("Say hello!", async () => { const blockhash = context.lastBlockhash; // We set up our instruction first. const ix = new TransactionInstruction({ @@ -27,7 +27,7 @@ describe('hello-solana', async () => { const transaction = await client.processTransaction(tx); assert(transaction.logMessages[0].startsWith(`Program ${PROGRAM_ID}`)); - assert(transaction.logMessages[1] === 'Program log: Hello, Solana!'); + assert(transaction.logMessages[1] === "Program log: Hello, Solana!"); assert(transaction.logMessages[2] === `Program log: Our program's Program ID: ${PROGRAM_ID}`); assert(transaction.logMessages[3].startsWith(`Program ${PROGRAM_ID} consumed`)); assert(transaction.logMessages[4] === `Program ${PROGRAM_ID} success`); diff --git a/basics/hello-solana/pinocchio/tests/index.test.ts b/basics/hello-solana/pinocchio/tests/index.test.ts index 734bad24f..985c2befa 100644 --- a/basics/hello-solana/pinocchio/tests/index.test.ts +++ b/basics/hello-solana/pinocchio/tests/index.test.ts @@ -1,17 +1,17 @@ -import { PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js'; -import { assert } from 'chai'; -import { ProgramTestContext, start } from 'solana-bankrun'; +import { PublicKey, Transaction, TransactionInstruction } from "@solana/web3.js"; +import { assert } from "chai"; +import { type ProgramTestContext, start } from "solana-bankrun"; -describe('hello-solana', () => { +describe("hello-solana", () => { const PROGRAM_ID = PublicKey.unique(); // load program in solana-bankrun let context: ProgramTestContext; before(async () => { - context = await start([{ name: 'hello_solana_program_pinocchio', programId: PROGRAM_ID }], []); + context = await start([{ name: "hello_solana_program_pinocchio", programId: PROGRAM_ID }], []); }); - it('Say hello!', async () => { + it("Say hello!", async () => { const client = context.banksClient; const payer = context.payer; const blockhash = context.lastBlockhash; @@ -30,8 +30,8 @@ describe('hello-solana', () => { const transaction = await client.processTransaction(tx); assert(transaction.logMessages[0].startsWith(`Program ${PROGRAM_ID}`)); - assert(transaction.logMessages[1] === 'Program log: Hello, Solana!'); - assert(transaction.logMessages[2] === `Program log: [${Array.from(PROGRAM_ID.toBytes()).join(', ')}]`); + assert(transaction.logMessages[1] === "Program log: Hello, Solana!"); + assert(transaction.logMessages[2] === `Program log: [${Array.from(PROGRAM_ID.toBytes()).join(", ")}]`); assert(transaction.logMessages[3].startsWith(`Program ${PROGRAM_ID} consumed`)); assert(transaction.logMessages[4] === `Program ${PROGRAM_ID} success`); assert(transaction.logMessages.length === 5); diff --git a/basics/pda-rent-payer/anchor/Anchor.toml b/basics/pda-rent-payer/anchor/Anchor.toml index 50b35bcf2..14b4bd938 100644 --- a/basics/pda-rent-payer/anchor/Anchor.toml +++ b/basics/pda-rent-payer/anchor/Anchor.toml @@ -2,15 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false -[programs.localnet] -pda_rent_payer = "7Hm9nsYVuBZ9rf8z9AMUHreZRv8Q4vLhqwdVTCawRZtA" +resolution = true +skip-lint = false -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +pda_rent_payer = "EC9R1o4AsK3hoeh61yNyr2xiDoorgyS4ZBmhYujNUsyN" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/pda-rent-payer/anchor/package.json b/basics/pda-rent-payer/anchor/package.json index 0696e9344..878e62db1 100644 --- a/basics/pda-rent-payer/anchor/package.json +++ b/basics/pda-rent-payer/anchor/package.json @@ -1,17 +1,17 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/pda-rent-payer/anchor/pnpm-lock.yaml b/basics/pda-rent-payer/anchor/pnpm-lock.yaml index 37a30dda9..271bd4550 100644 --- a/basics/pda-rent-payer/anchor/pnpm-lock.yaml +++ b/basics/pda-rent-payer/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -746,16 +746,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -773,7 +773,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/basics/pda-rent-payer/anchor/programs/anchor-program-example/Cargo.toml b/basics/pda-rent-payer/anchor/programs/anchor-program-example/Cargo.toml index 3a5db53ef..9cf22c479 100644 --- a/basics/pda-rent-payer/anchor/programs/anchor-program-example/Cargo.toml +++ b/basics/pda-rent-payer/anchor/programs/anchor-program-example/Cargo.toml @@ -20,8 +20,13 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/pda-rent-payer/anchor/programs/anchor-program-example/src/lib.rs b/basics/pda-rent-payer/anchor/programs/anchor-program-example/src/lib.rs index b5b31ead7..28ecc3c41 100644 --- a/basics/pda-rent-payer/anchor/programs/anchor-program-example/src/lib.rs +++ b/basics/pda-rent-payer/anchor/programs/anchor-program-example/src/lib.rs @@ -2,7 +2,7 @@ use anchor_lang::prelude::*; use instructions::*; pub mod instructions; -declare_id!("7Hm9nsYVuBZ9rf8z9AMUHreZRv8Q4vLhqwdVTCawRZtA"); +declare_id!("EC9R1o4AsK3hoeh61yNyr2xiDoorgyS4ZBmhYujNUsyN"); #[program] pub mod pda_rent_payer { diff --git a/basics/pda-rent-payer/anchor/programs/anchor-program-example/tests/test_pda_rent_payer.rs b/basics/pda-rent-payer/anchor/programs/anchor-program-example/tests/test_pda_rent_payer.rs new file mode 100644 index 000000000..3bc8c1f57 --- /dev/null +++ b/basics/pda-rent-payer/anchor/programs/anchor-program-example/tests/test_pda_rent_payer.rs @@ -0,0 +1,112 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Keypair) { + let program_id = pda_rent_payer::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/pda_rent_payer.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, payer) +} + +#[test] +fn test_init_rent_vault() { + let (mut svm, payer) = setup(); + let program_id = pda_rent_payer::id(); + + let (rent_vault_pda, _bump) = Pubkey::find_program_address(&[b"rent_vault"], &program_id); + + // Fund the rent vault with 1 SOL + let fund_amount: u64 = 1_000_000_000; + let init_ix = Instruction::new_with_bytes( + program_id, + &pda_rent_payer::instruction::InitRentVault { + fund_lamports: fund_amount, + } + .data(), + pda_rent_payer::accounts::InitRentVault { + payer: payer.pubkey(), + rent_vault: rent_vault_pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + // Verify the rent vault has the correct balance + let account = svm + .get_account(&rent_vault_pda) + .expect("Rent vault should exist"); + assert_eq!( + account.lamports, fund_amount, + "Rent vault should have 1 SOL" + ); +} + +#[test] +fn test_create_new_account_from_rent_vault() { + let (mut svm, payer) = setup(); + let program_id = pda_rent_payer::id(); + + let (rent_vault_pda, _bump) = Pubkey::find_program_address(&[b"rent_vault"], &program_id); + + // Fund the rent vault with 1 SOL + let fund_amount: u64 = 1_000_000_000; + let init_ix = Instruction::new_with_bytes( + program_id, + &pda_rent_payer::instruction::InitRentVault { + fund_lamports: fund_amount, + } + .data(), + pda_rent_payer::accounts::InitRentVault { + payer: payer.pubkey(), + rent_vault: rent_vault_pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + svm.expire_blockhash(); + + // Create a new account using the rent vault + let new_account = Keypair::new(); + let create_ix = Instruction::new_with_bytes( + program_id, + &pda_rent_payer::instruction::CreateNewAccount {}.data(), + pda_rent_payer::accounts::CreateNewAccount { + new_account: new_account.pubkey(), + rent_vault: rent_vault_pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![create_ix], + &[&payer, &new_account], + &payer.pubkey(), + ) + .unwrap(); + + // Verify the new account was created with minimum rent-exempt balance + let rent_exempt_balance = svm.minimum_balance_for_rent_exemption(0); + let account = svm + .get_account(&new_account.pubkey()) + .expect("New account should exist"); + assert_eq!( + account.lamports, rent_exempt_balance, + "New account should have rent-exempt balance" + ); +} diff --git a/basics/pda-rent-payer/anchor/tests/litesvm.test.ts b/basics/pda-rent-payer/anchor/tests/litesvm.test.ts index 35c9a3108..a1c0c2174 100644 --- a/basics/pda-rent-payer/anchor/tests/litesvm.test.ts +++ b/basics/pda-rent-payer/anchor/tests/litesvm.test.ts @@ -1,93 +1,87 @@ import anchor from "@anchor-lang/core"; import { - Keypair, - LAMPORTS_PER_SOL, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, + Keypair, + LAMPORTS_PER_SOL, + PublicKey, + SystemProgram, + Transaction, + TransactionInstruction, } from "@solana/web3.js"; import { assert } from "chai"; import { LiteSVM } from "litesvm"; import IDL from "../target/idl/pda_rent_payer.json" with { type: "json" }; describe("LiteSVM: PDA Rent-Payer", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(IDL.address); - const coder = new anchor.BorshCoder(IDL as anchor.Idl); - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(10000000000)); + const svm = new LiteSVM(); + const programId = new PublicKey(IDL.address); + const coder = new anchor.BorshCoder(IDL as anchor.Idl); + const payer = Keypair.generate(); + svm.airdrop(payer.publicKey, BigInt(10000000000)); - const programPath = new URL( - "../target/deploy/pda_rent_payer.so", - import.meta.url, - ).pathname; - svm.addProgramFromFile(programId, programPath); + const programPath = new URL("../target/deploy/pda_rent_payer.so", import.meta.url).pathname; + svm.addProgramFromFile(programId, programPath); - /** - * generate PDA for the Rent Vault - */ - const [rentVaultPDA] = PublicKey.findProgramAddressSync( - [Buffer.from("rent_vault")], - programId, - ); + /** + * generate PDA for the Rent Vault + */ + const [rentVaultPDA] = PublicKey.findProgramAddressSync([Buffer.from("rent_vault")], programId); - it("Initialize the Rent Vault", () => { - const ixArgs = { - fund_lamports: new anchor.BN(LAMPORTS_PER_SOL), - }; + it("Initialize the Rent Vault", () => { + const ixArgs = { + fund_lamports: new anchor.BN(LAMPORTS_PER_SOL), + }; - const data = coder.instruction.encode("init_rent_vault", ixArgs); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: rentVaultPDA, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); + const data = coder.instruction.encode("init_rent_vault", ixArgs); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: rentVaultPDA, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); - /** - * Fetch the account and check its rent vault account info - */ - const rentVaultAccountInfo = svm.getAccount(rentVaultPDA); + /** + * Fetch the account and check its rent vault account info + */ + const rentVaultAccountInfo = svm.getAccount(rentVaultPDA); - assert.equal(rentVaultAccountInfo.lamports, LAMPORTS_PER_SOL); - }); + assert.equal(rentVaultAccountInfo.lamports, LAMPORTS_PER_SOL); + }); - it("Create a new account using the Rent Vault", () => { - const newAccount = new Keypair(); + it("Create a new account using the Rent Vault", () => { + const newAccount = new Keypair(); - const data = coder.instruction.encode("create_new_account", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: newAccount.publicKey, isSigner: true, isWritable: true }, - { pubkey: rentVaultPDA, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); + const data = coder.instruction.encode("create_new_account", {}); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: newAccount.publicKey, isSigner: true, isWritable: true }, + { pubkey: rentVaultPDA, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer, newAccount); - svm.sendTransaction(tx); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer, newAccount); + svm.sendTransaction(tx); - /** - * Fetch the newAccount and check its rent - */ - const minLamports = svm.minimumBalanceForRentExemption(BigInt(0)); - const newAccountInfo = svm.getAccount(newAccount.publicKey); + /** + * Fetch the newAccount and check its rent + */ + const minLamports = svm.minimumBalanceForRentExemption(BigInt(0)); + const newAccountInfo = svm.getAccount(newAccount.publicKey); - assert.equal(newAccountInfo.lamports, Number(minLamports)); - }); + assert.equal(newAccountInfo.lamports, Number(minLamports)); + }); }); diff --git a/basics/pda-rent-payer/anchor/tests/test.ts b/basics/pda-rent-payer/anchor/tests/test.ts index 153d95d3f..1e8dc3a92 100644 --- a/basics/pda-rent-payer/anchor/tests/test.ts +++ b/basics/pda-rent-payer/anchor/tests/test.ts @@ -5,52 +5,48 @@ import { assert } from "chai"; import type { PdaRentPayer } from "../target/types/pda_rent_payer.ts"; describe("PDA Rent-Payer", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const wallet = provider.wallet as anchor.Wallet; - const connection = provider.connection; - const program = anchor.workspace.PdaRentPayer as anchor.Program; - - // PDA for the Rent Vault - const [rentVaultPDA] = PublicKey.findProgramAddressSync( - [Buffer.from("rent_vault")], - program.programId, - ); - - it("Initialize the Rent Vault", async () => { - // 1 SOL - const fundAmount = new BN(LAMPORTS_PER_SOL); - - await program.methods - .initRentVault(fundAmount) - .accounts({ - payer: wallet.publicKey, - }) - .rpc(); - - // Check rent vault balance - const accountInfo = - await program.provider.connection.getAccountInfo(rentVaultPDA); - assert(accountInfo.lamports === fundAmount.toNumber()); - }); - - it("Create a new account using the Rent Vault", async () => { - // Generate a new keypair for the new account - const newAccount = new Keypair(); - - await program.methods - .createNewAccount() - .accounts({ - newAccount: newAccount.publicKey, - }) - .signers([newAccount]) - .rpc(); - - // Minimum balance for rent exemption for new account - const lamports = await connection.getMinimumBalanceForRentExemption(0); - - // Check that the account was created - const accountInfo = await connection.getAccountInfo(newAccount.publicKey); - assert(accountInfo.lamports === lamports); - }); + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const wallet = provider.wallet as anchor.Wallet; + const connection = provider.connection; + const program = anchor.workspace.PdaRentPayer as anchor.Program; + + // PDA for the Rent Vault + const [rentVaultPDA] = PublicKey.findProgramAddressSync([Buffer.from("rent_vault")], program.programId); + + it("Initialize the Rent Vault", async () => { + // 1 SOL + const fundAmount = new BN(LAMPORTS_PER_SOL); + + await program.methods + .initRentVault(fundAmount) + .accounts({ + payer: wallet.publicKey, + }) + .rpc(); + + // Check rent vault balance + const accountInfo = await program.provider.connection.getAccountInfo(rentVaultPDA); + assert(accountInfo.lamports === fundAmount.toNumber()); + }); + + it("Create a new account using the Rent Vault", async () => { + // Generate a new keypair for the new account + const newAccount = new Keypair(); + + await program.methods + .createNewAccount() + .accounts({ + newAccount: newAccount.publicKey, + }) + .signers([newAccount]) + .rpc(); + + // Minimum balance for rent exemption for new account + const lamports = await connection.getMinimumBalanceForRentExemption(0); + + // Check that the account was created + const accountInfo = await connection.getAccountInfo(newAccount.publicKey); + assert(accountInfo.lamports === lamports); + }); }); diff --git a/basics/pda-rent-payer/anchor/tsconfig.json b/basics/pda-rent-payer/anchor/tsconfig.json index 59fe75cf0..beb254c00 100644 --- a/basics/pda-rent-payer/anchor/tsconfig.json +++ b/basics/pda-rent-payer/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], - "module": "nodenext", - "target": "es6", - "esModuleInterop": true - } + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "nodenext", + "target": "es6", + "esModuleInterop": true + } } diff --git a/basics/pda-rent-payer/native/tests/test.ts b/basics/pda-rent-payer/native/tests/test.ts index 03f17ca03..6c3a9c414 100644 --- a/basics/pda-rent-payer/native/tests/test.ts +++ b/basics/pda-rent-payer/native/tests/test.ts @@ -1,21 +1,12 @@ import { Buffer } from "node:buffer"; import { describe, test } from "node:test"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; import * as borsh from "borsh"; import { start } from "solana-bankrun"; describe("PDA Rent-Payer", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start( - [{ name: "pda_rent_payer_program", programId: PROGRAM_ID }], - [], - ); + const context = await start([{ name: "pda_rent_payer_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; @@ -42,10 +33,7 @@ describe("PDA Rent-Payer", async () => { } function deriveRentVaultPda() { - const pda = PublicKey.findProgramAddressSync( - [Buffer.from("rent_vault")], - PROGRAM_ID, - ); + const pda = PublicKey.findProgramAddressSync([Buffer.from("rent_vault")], PROGRAM_ID); console.log(`PDA: ${pda[0].toBase58()}`); return pda; } diff --git a/basics/pda-rent-payer/pinocchio/tests/test.ts b/basics/pda-rent-payer/pinocchio/tests/test.ts index b1af8db34..836c6aba3 100644 --- a/basics/pda-rent-payer/pinocchio/tests/test.ts +++ b/basics/pda-rent-payer/pinocchio/tests/test.ts @@ -1,14 +1,4 @@ -import { Buffer } from "node:buffer"; -import { describe, test } from "node:test"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; -import * as borsh from "borsh"; -import { start } from "solana-bankrun"; +import { describe } from "node:test"; describe("PDA Rent-Payer", async () => { console.log("PDA Rent-Payer"); diff --git a/basics/processing-instructions/anchor/Anchor.toml b/basics/processing-instructions/anchor/Anchor.toml index f08cbe3f0..0ddc6ba34 100644 --- a/basics/processing-instructions/anchor/Anchor.toml +++ b/basics/processing-instructions/anchor/Anchor.toml @@ -2,15 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false -[programs.localnet] -processing_instructions = "DgoL5J44aspizyUs9fcnpGEUJjWTLJRCfx8eYtUMYczf" +resolution = true +skip-lint = false -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +processing_instructions = "ErP5EBTkp343iNqC9HP5u7Eh8dyTn5tvKzSiaUpiKgHK" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/processing-instructions/anchor/package.json b/basics/processing-instructions/anchor/package.json index 0696e9344..878e62db1 100644 --- a/basics/processing-instructions/anchor/package.json +++ b/basics/processing-instructions/anchor/package.json @@ -1,17 +1,17 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/processing-instructions/anchor/pnpm-lock.yaml b/basics/processing-instructions/anchor/pnpm-lock.yaml index a439ab7e5..5a193f700 100644 --- a/basics/processing-instructions/anchor/pnpm-lock.yaml +++ b/basics/processing-instructions/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': @@ -755,16 +755,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -782,7 +782,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: diff --git a/basics/processing-instructions/anchor/programs/processing-instructions/Cargo.toml b/basics/processing-instructions/anchor/programs/processing-instructions/Cargo.toml index 8731d6e16..331c63a3d 100644 --- a/basics/processing-instructions/anchor/programs/processing-instructions/Cargo.toml +++ b/basics/processing-instructions/anchor/programs/processing-instructions/Cargo.toml @@ -20,8 +20,13 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/processing-instructions/anchor/programs/processing-instructions/src/lib.rs b/basics/processing-instructions/anchor/programs/processing-instructions/src/lib.rs index 48049f4e4..b52a76017 100644 --- a/basics/processing-instructions/anchor/programs/processing-instructions/src/lib.rs +++ b/basics/processing-instructions/anchor/programs/processing-instructions/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("DgoL5J44aspizyUs9fcnpGEUJjWTLJRCfx8eYtUMYczf"); +declare_id!("ErP5EBTkp343iNqC9HP5u7Eh8dyTn5tvKzSiaUpiKgHK"); #[program] pub mod processing_instructions { diff --git a/basics/processing-instructions/anchor/programs/processing-instructions/tests/test_processing_instructions.rs b/basics/processing-instructions/anchor/programs/processing-instructions/tests/test_processing_instructions.rs new file mode 100644 index 000000000..5e5d26b1b --- /dev/null +++ b/basics/processing-instructions/anchor/programs/processing-instructions/tests/test_processing_instructions.rs @@ -0,0 +1,49 @@ +use { + anchor_lang::{solana_program::instruction::Instruction, InstructionData, ToAccountMetas}, + litesvm::LiteSVM, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, solana_keypair::Keypair) { + let program_id = processing_instructions::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/processing_instructions.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, payer) +} + +#[test] +fn test_go_to_park() { + let (mut svm, payer) = setup(); + let program_id = processing_instructions::id(); + + // Test with short person (height 3) + let ix_short = Instruction::new_with_bytes( + program_id, + &processing_instructions::instruction::GoToPark { + name: "Jimmy".to_string(), + height: 3, + } + .data(), + processing_instructions::accounts::Park {}.to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![ix_short], &[&payer], &payer.pubkey()) + .unwrap(); + + svm.expire_blockhash(); + + // Test with tall person (height 10) + let ix_tall = Instruction::new_with_bytes( + program_id, + &processing_instructions::instruction::GoToPark { + name: "Mary".to_string(), + height: 10, + } + .data(), + processing_instructions::accounts::Park {}.to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![ix_tall], &[&payer], &payer.pubkey()) + .unwrap(); +} diff --git a/basics/processing-instructions/anchor/tests/litesvm.test.ts b/basics/processing-instructions/anchor/tests/litesvm.test.ts index 096d394ee..b943c6780 100644 --- a/basics/processing-instructions/anchor/tests/litesvm.test.ts +++ b/basics/processing-instructions/anchor/tests/litesvm.test.ts @@ -1,83 +1,73 @@ import anchor from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, Transaction, TransactionInstruction } from "@solana/web3.js"; import { LiteSVM } from "litesvm"; -import IDL from "../target/idl/processing_instructions.json" with { - type: "json", -}; +import IDL from "../target/idl/processing_instructions.json" with { type: "json" }; describe("LiteSVM: custom-instruction-data", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(IDL.address); - /** - * Creates a coder to easily build and encode program instructions based on the IDL. - */ - const coder = new anchor.BorshCoder(IDL as anchor.Idl); + const svm = new LiteSVM(); + const programId = new PublicKey(IDL.address); + /** + * Creates a coder to easily build and encode program instructions based on the IDL. + */ + const coder = new anchor.BorshCoder(IDL as anchor.Idl); - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(1000000000)); + const payer = Keypair.generate(); + svm.airdrop(payer.publicKey, BigInt(1000000000)); - /** - * Load the processing_instructions program binary into the LiteSVM instance - * for local testing and simulation. - */ - const programPath = new URL( - "../target/deploy/processing_instructions.so", - import.meta.url, - ).pathname; - svm.addProgramFromFile(programId, programPath); + /** + * Load the processing_instructions program binary into the LiteSVM instance + * for local testing and simulation. + */ + const programPath = new URL("../target/deploy/processing_instructions.so", import.meta.url).pathname; + svm.addProgramFromFile(programId, programPath); - it("Go to the park!", () => { - /** - * Create an instruction for the 'go_to_park' method using the Anchor coder. - * Arguments are needed for this instruction so we give inside `{}`. - */ - const ixArgs = { - name: "Jimmy", - height: 5, - }; - const data = coder.instruction.encode("go_to_park", ixArgs); + it("Go to the park!", () => { + /** + * Create an instruction for the 'go_to_park' method using the Anchor coder. + * Arguments are needed for this instruction so we give inside `{}`. + */ + const ixArgs = { + name: "Jimmy", + height: 5, + }; + const data = coder.instruction.encode("go_to_park", ixArgs); - /** - * Build and sign a transaction to call the 'go_to_park' instruction - * on the processing_instructions program with LiteSVM. - */ - const ix = new TransactionInstruction({ - keys: [], - programId, - data, - }); + /** + * Build and sign a transaction to call the 'go_to_park' instruction + * on the processing_instructions program with LiteSVM. + */ + const ix = new TransactionInstruction({ + keys: [], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - svm.expireBlockhash(); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + svm.expireBlockhash(); - /** - * For Mary , height: 10 - */ - const ixArgs2 = { - name: "Mary", - height: 10, - }; - const data2 = coder.instruction.encode("go_to_park", ixArgs2); + /** + * For Mary , height: 10 + */ + const ixArgs2 = { + name: "Mary", + height: 10, + }; + const data2 = coder.instruction.encode("go_to_park", ixArgs2); - const ix2 = new TransactionInstruction({ - keys: [], - programId, - data: data2, - }); + const ix2 = new TransactionInstruction({ + keys: [], + programId, + data: data2, + }); - const tx2 = new Transaction().add(ix2); - tx2.feePayer = payer.publicKey; - tx2.recentBlockhash = svm.latestBlockhash(); - tx2.sign(payer); - svm.sendTransaction(tx2); - }); + const tx2 = new Transaction().add(ix2); + tx2.feePayer = payer.publicKey; + tx2.recentBlockhash = svm.latestBlockhash(); + tx2.sign(payer); + svm.sendTransaction(tx2); + }); }); diff --git a/basics/processing-instructions/anchor/tests/test.ts b/basics/processing-instructions/anchor/tests/test.ts index debaf2f63..5e26f7296 100644 --- a/basics/processing-instructions/anchor/tests/test.ts +++ b/basics/processing-instructions/anchor/tests/test.ts @@ -1,15 +1,15 @@ -import * as anchor from '@anchor-lang/core'; -import type { ProcessingInstructions } from '../target/types/processing_instructions'; +import * as anchor from "@anchor-lang/core"; +import type { ProcessingInstructions } from "../target/types/processing_instructions"; -describe('custom-instruction-data', () => { +describe("custom-instruction-data", () => { const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); const program = anchor.workspace.ProcessingInstructions as anchor.Program; - it('Go to the park!', async () => { + it("Go to the park!", async () => { // Again, Anchor makes it super simple. // - await program.methods.goToPark('Jimmy', 3).accounts({}).rpc(); - await program.methods.goToPark('Mary', 10).accounts({}).rpc(); + await program.methods.goToPark("Jimmy", 3).accounts({}).rpc(); + await program.methods.goToPark("Mary", 10).accounts({}).rpc(); }); }); diff --git a/basics/processing-instructions/anchor/tsconfig.json b/basics/processing-instructions/anchor/tsconfig.json index 59fe75cf0..beb254c00 100644 --- a/basics/processing-instructions/anchor/tsconfig.json +++ b/basics/processing-instructions/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], - "module": "nodenext", - "target": "es6", - "esModuleInterop": true - } + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "nodenext", + "target": "es6", + "esModuleInterop": true + } } diff --git a/basics/processing-instructions/native/program/Cargo.toml b/basics/processing-instructions/native/program/Cargo.toml index 2855d519d..d3af395c4 100644 --- a/basics/processing-instructions/native/program/Cargo.toml +++ b/basics/processing-instructions/native/program/Cargo.toml @@ -19,7 +19,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-pubkey = "3.0.0" diff --git a/basics/processing-instructions/native/tests/test.ts b/basics/processing-instructions/native/tests/test.ts index 3964cc912..e77b04772 100644 --- a/basics/processing-instructions/native/tests/test.ts +++ b/basics/processing-instructions/native/tests/test.ts @@ -1,19 +1,19 @@ -import { Buffer } from 'node:buffer'; -import { describe, test } from 'node:test'; -import { PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { start } from 'solana-bankrun'; +import { Buffer } from "node:buffer"; +import { describe, test } from "node:test"; +import { PublicKey, Transaction, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { start } from "solana-bankrun"; -describe('custom-instruction-data', async () => { +describe("custom-instruction-data", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'processing_instructions_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "processing_instructions_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; const InstructionDataSchema = { struct: { - name: 'string', - height: 'u32', + name: "string", + height: "u32", }, }; @@ -21,11 +21,17 @@ describe('custom-instruction-data', async () => { return Buffer.from(borsh.serialize(schema, data)); } - test('Go to the park!', async () => { + test("Go to the park!", async () => { const blockhash = context.lastBlockhash; - const jimmy = borshSerialize(InstructionDataSchema, { name: 'Jimmy', height: 3 }); - const mary = borshSerialize(InstructionDataSchema, { name: 'Mary', height: 10 }); + const jimmy = borshSerialize(InstructionDataSchema, { + name: "Jimmy", + height: 3, + }); + const mary = borshSerialize(InstructionDataSchema, { + name: "Mary", + height: 10, + }); const ix1 = new TransactionInstruction({ keys: [{ pubkey: payer.publicKey, isSigner: true, isWritable: true }], diff --git a/basics/processing-instructions/pinocchio/program/Cargo.toml b/basics/processing-instructions/pinocchio/program/Cargo.toml index 96beaced7..5e202b590 100644 --- a/basics/processing-instructions/pinocchio/program/Cargo.toml +++ b/basics/processing-instructions/pinocchio/program/Cargo.toml @@ -18,7 +18,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-pubkey = "3.0.0" diff --git a/basics/processing-instructions/pinocchio/tests/test.ts b/basics/processing-instructions/pinocchio/tests/test.ts index b5be3aecb..a4fe7c67d 100644 --- a/basics/processing-instructions/pinocchio/tests/test.ts +++ b/basics/processing-instructions/pinocchio/tests/test.ts @@ -1,12 +1,4 @@ -import { Buffer } from "node:buffer"; -import { describe, test } from "node:test"; -import { - PublicKey, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; -import * as borsh from "borsh"; -import { start } from "solana-bankrun"; +import { describe } from "node:test"; describe("custom-instruction-data", async () => { console.log("custom-instruction-data"); diff --git a/basics/program-derived-addresses/anchor/Anchor.toml b/basics/program-derived-addresses/anchor/Anchor.toml index 846ff33de..4ec3dd439 100644 --- a/basics/program-derived-addresses/anchor/Anchor.toml +++ b/basics/program-derived-addresses/anchor/Anchor.toml @@ -2,15 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false -[programs.localnet] -program_derived_addresses_program = "oCCQRZyAbVxujyd8m57MPmDzZDmy2FoKW4ULS7KofCE" +resolution = true +skip-lint = false -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +program_derived_addresses_program = "GHC7zYxZ3mDfb9EunrPwbVd2FG8QpYbnVH3TEp9wBCCU" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/program-derived-addresses/anchor/package.json b/basics/program-derived-addresses/anchor/package.json index 0696e9344..878e62db1 100644 --- a/basics/program-derived-addresses/anchor/package.json +++ b/basics/program-derived-addresses/anchor/package.json @@ -1,17 +1,17 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/program-derived-addresses/anchor/pnpm-lock.yaml b/basics/program-derived-addresses/anchor/pnpm-lock.yaml index 685c53440..23aac405f 100644 --- a/basics/program-derived-addresses/anchor/pnpm-lock.yaml +++ b/basics/program-derived-addresses/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': @@ -758,16 +758,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -785,7 +785,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: diff --git a/basics/program-derived-addresses/anchor/programs/anchor-program-example/Cargo.toml b/basics/program-derived-addresses/anchor/programs/anchor-program-example/Cargo.toml index 05229b066..fe8f082a5 100644 --- a/basics/program-derived-addresses/anchor/programs/anchor-program-example/Cargo.toml +++ b/basics/program-derived-addresses/anchor/programs/anchor-program-example/Cargo.toml @@ -20,8 +20,14 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/program-derived-addresses/anchor/programs/anchor-program-example/src/lib.rs b/basics/program-derived-addresses/anchor/programs/anchor-program-example/src/lib.rs index 630b20c29..77b1501e1 100644 --- a/basics/program-derived-addresses/anchor/programs/anchor-program-example/src/lib.rs +++ b/basics/program-derived-addresses/anchor/programs/anchor-program-example/src/lib.rs @@ -5,7 +5,7 @@ use instructions::*; pub mod instructions; pub mod state; -declare_id!("oCCQRZyAbVxujyd8m57MPmDzZDmy2FoKW4ULS7KofCE"); +declare_id!("GHC7zYxZ3mDfb9EunrPwbVd2FG8QpYbnVH3TEp9wBCCU"); #[program] pub mod program_derived_addresses_program { diff --git a/basics/program-derived-addresses/anchor/programs/anchor-program-example/tests/test_program_derived_addresses.rs b/basics/program-derived-addresses/anchor/programs/anchor-program-example/tests/test_program_derived_addresses.rs new file mode 100644 index 000000000..173a42960 --- /dev/null +++ b/basics/program-derived-addresses/anchor/programs/anchor-program-example/tests/test_program_derived_addresses.rs @@ -0,0 +1,100 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + borsh::BorshDeserialize, + litesvm::LiteSVM, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, solana_keypair::Keypair) { + let program_id = program_derived_addresses_program::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/program_derived_addresses_program.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, payer) +} + +#[derive(BorshDeserialize)] +struct PageVisits { + page_visits: u32, + bump: u8, +} + +#[test] +fn test_create_and_increment_page_visits() { + let (mut svm, payer) = setup(); + let program_id = program_derived_addresses_program::id(); + + // Derive PDA + let (page_visits_pda, _bump) = + Pubkey::find_program_address(&[b"page_visits", payer.pubkey().as_ref()], &program_id); + + // Create page visits account + let create_ix = Instruction::new_with_bytes( + program_id, + &program_derived_addresses_program::instruction::CreatePageVisits {}.data(), + program_derived_addresses_program::accounts::CreatePageVisits { + payer: payer.pubkey(), + page_visits: page_visits_pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![create_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + // Verify initial state (page_visits = 0) + let account = svm.get_account(&page_visits_pda).expect("PDA should exist"); + let data = PageVisits::try_from_slice(&account.data[8..]).unwrap(); + assert_eq!(data.page_visits, 0, "Initial page visits should be 0"); + + svm.expire_blockhash(); + + // Increment page visits + let increment_ix = Instruction::new_with_bytes( + program_id, + &program_derived_addresses_program::instruction::IncrementPageVisits {}.data(), + program_derived_addresses_program::accounts::IncrementPageVisits { + user: payer.pubkey(), + page_visits: page_visits_pda, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![increment_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + // Verify page_visits = 1 + let account = svm.get_account(&page_visits_pda).expect("PDA should exist"); + let data = PageVisits::try_from_slice(&account.data[8..]).unwrap(); + assert_eq!( + data.page_visits, 1, + "Page visits should be 1 after increment" + ); + + svm.expire_blockhash(); + + // Increment again + let increment_ix2 = Instruction::new_with_bytes( + program_id, + &program_derived_addresses_program::instruction::IncrementPageVisits {}.data(), + program_derived_addresses_program::accounts::IncrementPageVisits { + user: payer.pubkey(), + page_visits: page_visits_pda, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![increment_ix2], &[&payer], &payer.pubkey()) + .unwrap(); + + // Verify page_visits = 2 + let account = svm.get_account(&page_visits_pda).expect("PDA should exist"); + let data = PageVisits::try_from_slice(&account.data[8..]).unwrap(); + assert_eq!( + data.page_visits, 2, + "Page visits should be 2 after second increment" + ); +} diff --git a/basics/program-derived-addresses/anchor/tests/litesvm.test.ts b/basics/program-derived-addresses/anchor/tests/litesvm.test.ts index 84c78cb7c..cf597e954 100644 --- a/basics/program-derived-addresses/anchor/tests/litesvm.test.ts +++ b/basics/program-derived-addresses/anchor/tests/litesvm.test.ts @@ -1,119 +1,99 @@ import anchor from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; import { assert } from "chai"; import { LiteSVM } from "litesvm"; -import IDL from "../target/idl/program_derived_addresses_program.json" with { - type: "json", -}; +import IDL from "../target/idl/program_derived_addresses_program.json" with { type: "json" }; describe("LiteSVM: PDA", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(IDL.address); - const coder = new anchor.BorshCoder(IDL as anchor.Idl); - - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(1000000000)); - - const programPath = new URL( - "../target/deploy/program_derived_addresses_program.so", - import.meta.url, - ).pathname; - svm.addProgramFromFile(programId, programPath); - - // PDA for the page visits account - const [pageVisitPDA] = PublicKey.findProgramAddressSync( - [Buffer.from("page_visits"), payer.publicKey.toBuffer()], - programId, - ); - - it("Create the page visits tracking PDA", () => { - const data = coder.instruction.encode("create_page_visits", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: pageVisitPDA, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - - //Fetch the pageVisitPDA account and check it page visit count - const pageVisitPDAAccInfo = svm.getAccount(pageVisitPDA); - const pageVisitAccount = coder.accounts.decode( - "PageVisits", - Buffer.from(pageVisitPDAAccInfo.data), - ); - - assert.equal(pageVisitAccount.page_visits, 0); - }); - - it("Visit the page!", () => { - const data = coder.instruction.encode("increment_page_visits", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: pageVisitPDA, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - svm.expireBlockhash(); - - //Fetch the pageVisitPDA account and check it page visit count - const pageVisitPDAAccInfo = svm.getAccount(pageVisitPDA); - const pageVisitAccount = coder.accounts.decode( - "PageVisits", - Buffer.from(pageVisitPDAAccInfo.data), - ); - - assert.equal(pageVisitAccount.page_visits, 1); - }); - - it("Again visit the page!", () => { - const data = coder.instruction.encode("increment_page_visits", {}); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: pageVisitPDA, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); - - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - - //Fetch the pageVisitPDA account and check it page visit count - const pageVisitPDAAccInfo = svm.getAccount(pageVisitPDA); - const pageVisitAccount = coder.accounts.decode( - "PageVisits", - Buffer.from(pageVisitPDAAccInfo.data), - ); - - assert.equal(pageVisitAccount.page_visits, 2); - }); + const svm = new LiteSVM(); + const programId = new PublicKey(IDL.address); + const coder = new anchor.BorshCoder(IDL as anchor.Idl); + + const payer = Keypair.generate(); + svm.airdrop(payer.publicKey, BigInt(1000000000)); + + const programPath = new URL("../target/deploy/program_derived_addresses_program.so", import.meta.url).pathname; + svm.addProgramFromFile(programId, programPath); + + // PDA for the page visits account + const [pageVisitPDA] = PublicKey.findProgramAddressSync( + [Buffer.from("page_visits"), payer.publicKey.toBuffer()], + programId, + ); + + it("Create the page visits tracking PDA", () => { + const data = coder.instruction.encode("create_page_visits", {}); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: pageVisitPDA, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + + //Fetch the pageVisitPDA account and check it page visit count + const pageVisitPDAAccInfo = svm.getAccount(pageVisitPDA); + const pageVisitAccount = coder.accounts.decode("PageVisits", Buffer.from(pageVisitPDAAccInfo.data)); + + assert.equal(pageVisitAccount.page_visits, 0); + }); + + it("Visit the page!", () => { + const data = coder.instruction.encode("increment_page_visits", {}); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: pageVisitPDA, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + svm.expireBlockhash(); + + //Fetch the pageVisitPDA account and check it page visit count + const pageVisitPDAAccInfo = svm.getAccount(pageVisitPDA); + const pageVisitAccount = coder.accounts.decode("PageVisits", Buffer.from(pageVisitPDAAccInfo.data)); + + assert.equal(pageVisitAccount.page_visits, 1); + }); + + it("Again visit the page!", () => { + const data = coder.instruction.encode("increment_page_visits", {}); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: pageVisitPDA, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); + + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + + //Fetch the pageVisitPDA account and check it page visit count + const pageVisitPDAAccInfo = svm.getAccount(pageVisitPDA); + const pageVisitAccount = coder.accounts.decode("PageVisits", Buffer.from(pageVisitPDAAccInfo.data)); + + assert.equal(pageVisitAccount.page_visits, 2); + }); }); diff --git a/basics/program-derived-addresses/anchor/tests/test.ts b/basics/program-derived-addresses/anchor/tests/test.ts index da096db2a..9e6663f27 100644 --- a/basics/program-derived-addresses/anchor/tests/test.ts +++ b/basics/program-derived-addresses/anchor/tests/test.ts @@ -4,51 +4,50 @@ import { assert } from "chai"; import type { ProgramDerivedAddressesProgram } from "../target/types/program_derived_addresses_program.ts"; describe("Anchor: PDAs", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - const program = anchor.workspace - .ProgramDerivedAddressesProgram as anchor.Program; - - // PDA for the page visits account - const [pageVisitPDA] = PublicKey.findProgramAddressSync( - [Buffer.from("page_visits"), payer.publicKey.toBuffer()], - program.programId, - ); - - it("Create the page visits tracking PDA", async () => { - await program.methods - .createPageVisits() - .accounts({ - payer: payer.publicKey, - }) - .rpc(); - - const pageVisits = await program.account.pageVisits.fetch(pageVisitPDA); - assert.equal(pageVisits.pageVisits, 0); - }); - - it("Visit the page!", async () => { - await program.methods - .incrementPageVisits() - .accounts({ - user: payer.publicKey, - }) - .rpc(); - - const pageVisits = await program.account.pageVisits.fetch(pageVisitPDA); - assert.equal(pageVisits.pageVisits, 1); - }); - - it("Again visit the page!", async () => { - await program.methods - .incrementPageVisits() - .accounts({ - user: payer.publicKey, - }) - .rpc(); - - const pageVisits = await program.account.pageVisits.fetch(pageVisitPDA); - assert.equal(pageVisits.pageVisits, 2); - }); + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const payer = provider.wallet as anchor.Wallet; + const program = anchor.workspace.ProgramDerivedAddressesProgram as anchor.Program; + + // PDA for the page visits account + const [pageVisitPDA] = PublicKey.findProgramAddressSync( + [Buffer.from("page_visits"), payer.publicKey.toBuffer()], + program.programId, + ); + + it("Create the page visits tracking PDA", async () => { + await program.methods + .createPageVisits() + .accounts({ + payer: payer.publicKey, + }) + .rpc(); + + const pageVisits = await program.account.pageVisits.fetch(pageVisitPDA); + assert.equal(pageVisits.pageVisits, 0); + }); + + it("Visit the page!", async () => { + await program.methods + .incrementPageVisits() + .accounts({ + user: payer.publicKey, + }) + .rpc(); + + const pageVisits = await program.account.pageVisits.fetch(pageVisitPDA); + assert.equal(pageVisits.pageVisits, 1); + }); + + it("Again visit the page!", async () => { + await program.methods + .incrementPageVisits() + .accounts({ + user: payer.publicKey, + }) + .rpc(); + + const pageVisits = await program.account.pageVisits.fetch(pageVisitPDA); + assert.equal(pageVisits.pageVisits, 2); + }); }); diff --git a/basics/program-derived-addresses/anchor/tsconfig.json b/basics/program-derived-addresses/anchor/tsconfig.json index 59fe75cf0..beb254c00 100644 --- a/basics/program-derived-addresses/anchor/tsconfig.json +++ b/basics/program-derived-addresses/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], - "module": "nodenext", - "target": "es6", - "esModuleInterop": true - } + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "nodenext", + "target": "es6", + "esModuleInterop": true + } } diff --git a/basics/program-derived-addresses/native/program/Cargo.toml b/basics/program-derived-addresses/native/program/Cargo.toml index 097ef4d8a..1251e8d8a 100644 --- a/basics/program-derived-addresses/native/program/Cargo.toml +++ b/basics/program-derived-addresses/native/program/Cargo.toml @@ -20,7 +20,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-pubkey = "3.0.0" diff --git a/basics/program-derived-addresses/native/tests/test.ts b/basics/program-derived-addresses/native/tests/test.ts index 805bc7083..3065e8c5f 100644 --- a/basics/program-derived-addresses/native/tests/test.ts +++ b/basics/program-derived-addresses/native/tests/test.ts @@ -1,20 +1,28 @@ -import { Buffer } from 'node:buffer'; -import { describe, test } from 'node:test'; -import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { start } from 'solana-bankrun'; +import { Buffer } from "node:buffer"; +import { describe, test } from "node:test"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { start } from "solana-bankrun"; -describe('PDAs', async () => { +describe("PDAs", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'program_derived_addresses_native_program', programId: PROGRAM_ID }], []); + const context = await start( + [ + { + name: "program_derived_addresses_native_program", + programId: PROGRAM_ID, + }, + ], + [], + ); const client = context.banksClient; const payer = context.payer; const rent = await client.getRent(); const PageVisitsSchema = { struct: { - page_visits: 'u32', - bump: 'u8', + page_visits: "u32", + bump: "u8", }, }; @@ -27,7 +35,7 @@ describe('PDAs', async () => { const testUser = Keypair.generate(); - test('Create a test user', async () => { + test("Create a test user", async () => { const ix = SystemProgram.createAccount({ fromPubkey: payer.publicKey, lamports: Number(rent.minimumBalance(BigInt(0))), @@ -47,10 +55,10 @@ describe('PDAs', async () => { }); function derivePageVisitsPda(userPubkey: PublicKey) { - return PublicKey.findProgramAddressSync([Buffer.from('page_visits'), userPubkey.toBuffer()], PROGRAM_ID); + return PublicKey.findProgramAddressSync([Buffer.from("page_visits"), userPubkey.toBuffer()], PROGRAM_ID); } - test('Create the page visits tracking PDA', async () => { + test("Create the page visits tracking PDA", async () => { const [pageVisitsPda, pageVisitsBump] = derivePageVisitsPda(testUser.publicKey); const ix = new TransactionInstruction({ keys: [ @@ -60,7 +68,10 @@ describe('PDAs', async () => { { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, ], programId: PROGRAM_ID, - data: borshSerialize(PageVisitsSchema, { page_visits: 0, bump: pageVisitsBump }), + data: borshSerialize(PageVisitsSchema, { + page_visits: 0, + bump: pageVisitsBump, + }), }); const tx = new Transaction(); const blockhash = context.lastBlockhash; @@ -70,7 +81,7 @@ describe('PDAs', async () => { await client.processTransaction(tx); }); - test('Visit the page!', async () => { + test("Visit the page!", async () => { const [pageVisitsPda, _] = derivePageVisitsPda(testUser.publicKey); const ix = new TransactionInstruction({ keys: [ @@ -88,7 +99,7 @@ describe('PDAs', async () => { await client.processTransaction(tx); }); - test('Visit the page!', async () => { + test("Visit the page!", async () => { const [pageVisitsPda, _] = derivePageVisitsPda(testUser.publicKey); const ix = new TransactionInstruction({ keys: [ @@ -106,10 +117,13 @@ describe('PDAs', async () => { await client.processTransaction(tx); }); - test('Read page visits', async () => { + test("Read page visits", async () => { const [pageVisitsPda, _] = derivePageVisitsPda(testUser.publicKey); const accountInfo = await client.getAccount(pageVisitsPda); - const readPageVisits = borsh.deserialize(PageVisitsSchema, Buffer.from(accountInfo.data)) as { page_visits: number; bump: number }; + const readPageVisits = borsh.deserialize(PageVisitsSchema, Buffer.from(accountInfo.data)) as { + page_visits: number; + bump: number; + }; console.log(`Number of page visits: ${readPageVisits.page_visits}`); }); }); diff --git a/basics/program-derived-addresses/pinocchio/program/Cargo.toml b/basics/program-derived-addresses/pinocchio/program/Cargo.toml index 4b255c5eb..e803884e6 100644 --- a/basics/program-derived-addresses/pinocchio/program/Cargo.toml +++ b/basics/program-derived-addresses/pinocchio/program/Cargo.toml @@ -19,7 +19,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-pubkey = "3.0.0" diff --git a/basics/program-derived-addresses/pinocchio/tests/test.ts b/basics/program-derived-addresses/pinocchio/tests/test.ts index b197963e8..892781bf9 100644 --- a/basics/program-derived-addresses/pinocchio/tests/test.ts +++ b/basics/program-derived-addresses/pinocchio/tests/test.ts @@ -1,14 +1,4 @@ -import { Buffer } from "node:buffer"; -import { describe, test } from "node:test"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; -import * as borsh from "borsh"; -import { start } from "solana-bankrun"; +import { describe } from "node:test"; describe("PDAs", async () => { console.log("PDAS"); diff --git a/basics/realloc/anchor/Anchor.toml b/basics/realloc/anchor/Anchor.toml index f6b6906d1..77466e746 100644 --- a/basics/realloc/anchor/Anchor.toml +++ b/basics/realloc/anchor/Anchor.toml @@ -2,17 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false [programs.localnet] -anchor_realloc = "Fod47xKXjdHVQDzkFPBvfdWLm8gEAV4iMSXkfUzCHiSD" - -# [registry] section removed — no longer used in Anchor 1.0 +anchor_realloc = "4JzDy7ZPoTzSxWCFu8dmxFqEyJzLeXacYJ5xDxopt5vz" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/realloc/anchor/migrations/deploy.ts b/basics/realloc/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/basics/realloc/anchor/migrations/deploy.ts +++ b/basics/realloc/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/basics/realloc/anchor/package.json b/basics/realloc/anchor/package.json index 3335c7917..a5ef7c15b 100644 --- a/basics/realloc/anchor/package.json +++ b/basics/realloc/anchor/package.json @@ -1,22 +1,22 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.4.1", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.4.1", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/realloc/anchor/pnpm-lock.yaml b/basics/realloc/anchor/pnpm-lock.yaml index f7baf21bd..28bd50a78 100644 --- a/basics/realloc/anchor/pnpm-lock.yaml +++ b/basics/realloc/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -45,18 +45,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': @@ -766,16 +766,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -793,7 +793,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: diff --git a/basics/realloc/anchor/programs/anchor-realloc/Cargo.toml b/basics/realloc/anchor/programs/anchor-realloc/Cargo.toml index d7a7d349a..7ad0e5d94 100644 --- a/basics/realloc/anchor/programs/anchor-realloc/Cargo.toml +++ b/basics/realloc/anchor/programs/anchor-realloc/Cargo.toml @@ -20,8 +20,14 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/realloc/anchor/programs/anchor-realloc/src/lib.rs b/basics/realloc/anchor/programs/anchor-realloc/src/lib.rs index 7a0abc572..54ad70803 100644 --- a/basics/realloc/anchor/programs/anchor-realloc/src/lib.rs +++ b/basics/realloc/anchor/programs/anchor-realloc/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("Fod47xKXjdHVQDzkFPBvfdWLm8gEAV4iMSXkfUzCHiSD"); +declare_id!("4JzDy7ZPoTzSxWCFu8dmxFqEyJzLeXacYJ5xDxopt5vz"); #[program] pub mod anchor_realloc { diff --git a/basics/realloc/anchor/programs/anchor-realloc/tests/test_realloc.rs b/basics/realloc/anchor/programs/anchor-realloc/tests/test_realloc.rs new file mode 100644 index 000000000..ffc045d2a --- /dev/null +++ b/basics/realloc/anchor/programs/anchor-realloc/tests/test_realloc.rs @@ -0,0 +1,177 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, system_program}, + InstructionData, ToAccountMetas, + }, + borsh::BorshDeserialize, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +#[derive(BorshDeserialize)] +struct MessageAccount { + _discriminator: [u8; 8], + message: String, +} + +fn fetch_message(svm: &LiteSVM, pubkey: &anchor_lang::prelude::Pubkey) -> String { + let account = svm.get_account(pubkey).unwrap(); + let data = MessageAccount::try_from_slice(&account.data).unwrap(); + data.message +} + +#[test] +fn test_initialize() { + let program_id = anchor_realloc::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/anchor_realloc.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let message_keypair = Keypair::new(); + + let instruction = Instruction::new_with_bytes( + program_id, + &anchor_realloc::instruction::Initialize { + input: "hello".to_string(), + } + .data(), + anchor_realloc::accounts::Initialize { + payer: payer.pubkey(), + message_account: message_keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &message_keypair], + &payer.pubkey(), + ) + .unwrap(); + + let msg_text = fetch_message(&svm, &message_keypair.pubkey()); + assert_eq!(msg_text, "hello"); + + // Verify account size: 8 (discriminator) + 4 (string length) + 5 ("hello") + let account = svm.get_account(&message_keypair.pubkey()).unwrap(); + assert_eq!(account.data.len(), 8 + 4 + 5); +} + +#[test] +fn test_update_grows() { + let program_id = anchor_realloc::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/anchor_realloc.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let message_keypair = Keypair::new(); + + // Initialize with "hello" + let init_ix = Instruction::new_with_bytes( + program_id, + &anchor_realloc::instruction::Initialize { + input: "hello".to_string(), + } + .data(), + anchor_realloc::accounts::Initialize { + payer: payer.pubkey(), + message_account: message_keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![init_ix], + &[&payer, &message_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Update to "hello world" (grows the account) + svm.expire_blockhash(); + let update_ix = Instruction::new_with_bytes( + program_id, + &anchor_realloc::instruction::Update { + input: "hello world".to_string(), + } + .data(), + anchor_realloc::accounts::Update { + payer: payer.pubkey(), + message_account: message_keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![update_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + let msg_text = fetch_message(&svm, &message_keypair.pubkey()); + assert_eq!(msg_text, "hello world"); + + let account = svm.get_account(&message_keypair.pubkey()).unwrap(); + assert_eq!(account.data.len(), 8 + 4 + 11); +} + +#[test] +fn test_update_shrinks() { + let program_id = anchor_realloc::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/anchor_realloc.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let message_keypair = Keypair::new(); + + // Initialize with "hello world" + let init_ix = Instruction::new_with_bytes( + program_id, + &anchor_realloc::instruction::Initialize { + input: "hello world".to_string(), + } + .data(), + anchor_realloc::accounts::Initialize { + payer: payer.pubkey(), + message_account: message_keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![init_ix], + &[&payer, &message_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Update to "hi" (shrinks the account) + svm.expire_blockhash(); + let update_ix = Instruction::new_with_bytes( + program_id, + &anchor_realloc::instruction::Update { + input: "hi".to_string(), + } + .data(), + anchor_realloc::accounts::Update { + payer: payer.pubkey(), + message_account: message_keypair.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![update_ix], &[&payer], &payer.pubkey()) + .unwrap(); + + let msg_text = fetch_message(&svm, &message_keypair.pubkey()); + assert_eq!(msg_text, "hi"); + + let account = svm.get_account(&message_keypair.pubkey()).unwrap(); + assert_eq!(account.data.len(), 8 + 4 + 2); +} diff --git a/basics/realloc/anchor/tests/litesvm.test.ts b/basics/realloc/anchor/tests/litesvm.test.ts index e45976d50..e83294416 100644 --- a/basics/realloc/anchor/tests/litesvm.test.ts +++ b/basics/realloc/anchor/tests/litesvm.test.ts @@ -1,125 +1,107 @@ import anchor from "@anchor-lang/core"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; import { assert } from "chai"; import { LiteSVM } from "litesvm"; import IDL from "../target/idl/anchor_realloc.json" with { type: "json" }; describe("LiteSVM: realloc", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(IDL.address); - const coder = new anchor.BorshCoder(IDL as anchor.Idl); + const svm = new LiteSVM(); + const programId = new PublicKey(IDL.address); + const coder = new anchor.BorshCoder(IDL as anchor.Idl); - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(1000000000)); + const payer = Keypair.generate(); + svm.airdrop(payer.publicKey, BigInt(1000000000)); - const programPath = new URL( - "../target/deploy/anchor_realloc.so", - import.meta.url, - ).pathname; - svm.addProgramFromFile(programId, programPath); + const programPath = new URL("../target/deploy/anchor_realloc.so", import.meta.url).pathname; + svm.addProgramFromFile(programId, programPath); - // PDA for the message account - const messageAccount = new Keypair(); + // PDA for the message account + const messageAccount = new Keypair(); - it("Is initialized!", () => { - const message = "hello"; - const data = coder.instruction.encode("initialize", { - input: message, - }); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: messageAccount.publicKey, isSigner: true, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); + it("Is initialized!", () => { + const message = "hello"; + const data = coder.instruction.encode("initialize", { + input: message, + }); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: messageAccount.publicKey, isSigner: true, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer, messageAccount); - svm.sendTransaction(tx); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer, messageAccount); + svm.sendTransaction(tx); - //Fetch the message account and check it message - const messageAccInfo = svm.getAccount(messageAccount.publicKey); - const messageAcc = coder.accounts.decode( - "Message", - Buffer.from(messageAccInfo.data), - ); - assert.equal(messageAccInfo.data.length, 8 + 4 + message.length); - assert.equal(messageAcc.message, message); - }); + //Fetch the message account and check it message + const messageAccInfo = svm.getAccount(messageAccount.publicKey); + const messageAcc = coder.accounts.decode("Message", Buffer.from(messageAccInfo.data)); + assert.equal(messageAccInfo.data.length, 8 + 4 + message.length); + assert.equal(messageAcc.message, message); + }); - it("Update", () => { - const message = "hello world"; - const data = coder.instruction.encode("update", { - input: message, - }); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: messageAccount.publicKey, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); + it("Update", () => { + const message = "hello world"; + const data = coder.instruction.encode("update", { + input: message, + }); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: messageAccount.publicKey, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - svm.expireBlockhash(); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + svm.expireBlockhash(); - //Fetch the message account and check it message - const messageAccInfo = svm.getAccount(messageAccount.publicKey); - const messageAcc = coder.accounts.decode( - "Message", - Buffer.from(messageAccInfo.data), - ); - assert.equal(messageAccInfo.data.length, 8 + 4 + message.length); - assert.equal(messageAcc.message, message); - }); + //Fetch the message account and check it message + const messageAccInfo = svm.getAccount(messageAccount.publicKey); + const messageAcc = coder.accounts.decode("Message", Buffer.from(messageAccInfo.data)); + assert.equal(messageAccInfo.data.length, 8 + 4 + message.length); + assert.equal(messageAcc.message, message); + }); - it("Again update", () => { - const message = "hi"; - const data = coder.instruction.encode("update", { - input: message, - }); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: messageAccount.publicKey, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); + it("Again update", () => { + const message = "hi"; + const data = coder.instruction.encode("update", { + input: message, + }); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: messageAccount.publicKey, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); - svm.expireBlockhash(); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); + svm.expireBlockhash(); - //Fetch the message account and check it message - const messageAccInfo = svm.getAccount(messageAccount.publicKey); - const messageAcc = coder.accounts.decode( - "Message", - Buffer.from(messageAccInfo.data), - ); + //Fetch the message account and check it message + const messageAccInfo = svm.getAccount(messageAccount.publicKey); + const messageAcc = coder.accounts.decode("Message", Buffer.from(messageAccInfo.data)); - assert.equal(messageAccInfo.data.length, 8 + 4 + message.length); - assert.equal(messageAcc.message, message); - }); + assert.equal(messageAccInfo.data.length, 8 + 4 + message.length); + assert.equal(messageAcc.message, message); + }); }); diff --git a/basics/realloc/anchor/tests/test.ts b/basics/realloc/anchor/tests/test.ts index be04c637d..8ae3ab45d 100644 --- a/basics/realloc/anchor/tests/test.ts +++ b/basics/realloc/anchor/tests/test.ts @@ -5,68 +5,68 @@ import { assert } from "chai"; import type { AnchorRealloc } from "../target/types/anchor_realloc.ts"; describe("Anchor: realloc", () => { - // Configure the client to use the local cluster. - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - const connection = provider.connection; + // Configure the client to use the local cluster. + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const payer = provider.wallet as anchor.Wallet; + const connection = provider.connection; - const program = anchor.workspace.AnchorRealloc as Program; + const program = anchor.workspace.AnchorRealloc as Program; - const messageAccount = new Keypair(); + const messageAccount = new Keypair(); - // helper function to check the account data and message - async function checkAccount(publicKey, expectedMessage) { - const accountInfo = await connection.getAccountInfo(publicKey); - const accountData = await program.account.message.fetch(publicKey); + // helper function to check the account data and message + async function checkAccount(publicKey, expectedMessage) { + const accountInfo = await connection.getAccountInfo(publicKey); + const accountData = await program.account.message.fetch(publicKey); - // 8 bytes for the discriminator, - // 4 bytes for the length of the message, - // and the length of the message - assert.equal(accountInfo.data.length, 8 + 4 + expectedMessage.length); - assert.equal(accountData.message, expectedMessage); - } + // 8 bytes for the discriminator, + // 4 bytes for the length of the message, + // and the length of the message + assert.equal(accountInfo.data.length, 8 + 4 + expectedMessage.length); + assert.equal(accountData.message, expectedMessage); + } - it("Is initialized!", async () => { - const input = "hello"; + it("Is initialized!", async () => { + const input = "hello"; - await program.methods - .initialize(input) - .accounts({ - payer: payer.publicKey, - messageAccount: messageAccount.publicKey, - }) - .signers([messageAccount]) - .rpc(); + await program.methods + .initialize(input) + .accounts({ + payer: payer.publicKey, + messageAccount: messageAccount.publicKey, + }) + .signers([messageAccount]) + .rpc(); - await checkAccount(messageAccount.publicKey, input); - }); + await checkAccount(messageAccount.publicKey, input); + }); - it("Update", async () => { - const input = "hello world"; + it("Update", async () => { + const input = "hello world"; - await program.methods - .update(input) - .accounts({ - payer: payer.publicKey, - messageAccount: messageAccount.publicKey, - }) - .rpc(); + await program.methods + .update(input) + .accounts({ + payer: payer.publicKey, + messageAccount: messageAccount.publicKey, + }) + .rpc(); - await checkAccount(messageAccount.publicKey, input); - }); + await checkAccount(messageAccount.publicKey, input); + }); - it("Again update", async () => { - const input = "hi"; + it("Again update", async () => { + const input = "hi"; - await program.methods - .update(input) - .accounts({ - payer: payer.publicKey, - messageAccount: messageAccount.publicKey, - }) - .rpc(); + await program.methods + .update(input) + .accounts({ + payer: payer.publicKey, + messageAccount: messageAccount.publicKey, + }) + .rpc(); - await checkAccount(messageAccount.publicKey, input); - }); + await checkAccount(messageAccount.publicKey, input); + }); }); diff --git a/basics/realloc/anchor/tsconfig.json b/basics/realloc/anchor/tsconfig.json index 59fe75cf0..beb254c00 100644 --- a/basics/realloc/anchor/tsconfig.json +++ b/basics/realloc/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], - "module": "nodenext", - "target": "es6", - "esModuleInterop": true - } + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "nodenext", + "target": "es6", + "esModuleInterop": true + } } diff --git a/basics/realloc/native/program/Cargo.toml b/basics/realloc/native/program/Cargo.toml index 3c8672f61..8a763a8e1 100644 --- a/basics/realloc/native/program/Cargo.toml +++ b/basics/realloc/native/program/Cargo.toml @@ -20,7 +20,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/realloc/native/tests/realloc.test.ts b/basics/realloc/native/tests/realloc.test.ts index 08c39058c..53ef0b78c 100644 --- a/basics/realloc/native/tests/realloc.test.ts +++ b/basics/realloc/native/tests/realloc.test.ts @@ -1,6 +1,6 @@ -import { describe, test } from 'node:test'; -import { Keypair, PublicKey, Transaction } from '@solana/web3.js'; -import { start } from 'solana-bankrun'; +import { describe, test } from "node:test"; +import { Keypair, PublicKey, Transaction } from "@solana/web3.js"; +import { start } from "solana-bankrun"; import { AddressInfo, createCreateInstruction, @@ -8,19 +8,27 @@ import { createReallocateZeroInitInstruction, EnhancedAddressInfo, WorkInfo, -} from '../ts'; +} from "../ts"; -describe('Realloc!', async () => { +describe("Realloc!", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'realloc_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "realloc_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; const testAccount = Keypair.generate(); - test('Create the account with data', async () => { + test("Create the account with data", async () => { console.log(`${testAccount.publicKey}`); - const ix = createCreateInstruction(testAccount.publicKey, payer.publicKey, PROGRAM_ID, 'Jacob', 123, 'Main St.', 'Chicago'); + const ix = createCreateInstruction( + testAccount.publicKey, + payer.publicKey, + PROGRAM_ID, + "Jacob", + 123, + "Main St.", + "Chicago", + ); const tx = new Transaction(); tx.recentBlockhash = context.lastBlockhash; @@ -30,8 +38,14 @@ describe('Realloc!', async () => { await printAddressInfo(testAccount.publicKey); }); - test('Reallocate WITHOUT zero init', async () => { - const ix = createReallocateWithoutZeroInitInstruction(testAccount.publicKey, payer.publicKey, PROGRAM_ID, 'Illinois', 12345); + test("Reallocate WITHOUT zero init", async () => { + const ix = createReallocateWithoutZeroInitInstruction( + testAccount.publicKey, + payer.publicKey, + PROGRAM_ID, + "Illinois", + 12345, + ); const tx = new Transaction(); const [blockHash, _blockHeight] = await client.getLatestBlockhash(); tx.recentBlockhash = blockHash; @@ -41,8 +55,16 @@ describe('Realloc!', async () => { await printEnhancedAddressInfo(testAccount.publicKey); }); - test('Reallocate WITH zero init', async () => { - const ix = createReallocateZeroInitInstruction(testAccount.publicKey, payer.publicKey, PROGRAM_ID, 'Pete', 'Engineer', 'Solana Labs', 2); + test("Reallocate WITH zero init", async () => { + const ix = createReallocateZeroInitInstruction( + testAccount.publicKey, + payer.publicKey, + PROGRAM_ID, + "Pete", + "Engineer", + "Solana Labs", + 2, + ); const tx = new Transaction(); const [blockHash, _blockHeight] = await client.getLatestBlockhash(); tx.recentBlockhash = blockHash; @@ -58,7 +80,7 @@ describe('Realloc!', async () => { const data = (await client.getAccount(pubkey))?.data; if (data) { const addressInfo = AddressInfo.fromBuffer(Buffer.from(data)); - console.log('Address info:'); + console.log("Address info:"); console.log(` Name: ${addressInfo.name}`); console.log(` House Num: ${addressInfo.house_number}`); console.log(` Street: ${addressInfo.street}`); @@ -71,7 +93,7 @@ describe('Realloc!', async () => { const data = (await client.getAccount(pubkey))?.data; if (data) { const enhancedAddressInfo = EnhancedAddressInfo.fromBuffer(Buffer.from(data)); - console.log('Enhanced Address info:'); + console.log("Enhanced Address info:"); console.log(` Name: ${enhancedAddressInfo.name}`); console.log(` House Num: ${enhancedAddressInfo.house_number}`); console.log(` Street: ${enhancedAddressInfo.street}`); @@ -86,7 +108,7 @@ describe('Realloc!', async () => { const data = (await client.getAccount(pubkey))?.data; if (data) { const workInfo = WorkInfo.fromBuffer(Buffer.from(data)); - console.log('Work info:'); + console.log("Work info:"); console.log(` Name: ${workInfo.name}`); console.log(` Position: ${workInfo.position}`); console.log(` Company: ${workInfo.company}`); diff --git a/basics/realloc/native/ts/index.ts b/basics/realloc/native/ts/index.ts index 70c7f3510..9cfd68485 100644 --- a/basics/realloc/native/ts/index.ts +++ b/basics/realloc/native/ts/index.ts @@ -1,7 +1,7 @@ -export * from './instructions/create'; -export * from './instructions/instruction'; -export * from './instructions/reallocate'; -export * from './state/address-info'; -export * from './state/enhanced-address-info'; -export * from './state/work-info'; -export * from './util/util'; +export * from "./instructions/create"; +export * from "./instructions/instruction"; +export * from "./instructions/reallocate"; +export * from "./state/address-info"; +export * from "./state/enhanced-address-info"; +export * from "./state/work-info"; +export * from "./util/util"; diff --git a/basics/realloc/native/ts/instructions/create.ts b/basics/realloc/native/ts/instructions/create.ts index d60a9c800..3fbc6a84e 100644 --- a/basics/realloc/native/ts/instructions/create.ts +++ b/basics/realloc/native/ts/instructions/create.ts @@ -1,7 +1,7 @@ -import { Buffer } from 'node:buffer'; -import { type PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { ReallocInstruction } from './instruction'; +import { Buffer } from "node:buffer"; +import { type PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { ReallocInstruction } from "./instruction"; export class Create { instruction: ReallocInstruction; @@ -37,13 +37,13 @@ export const CreateSchema = new Map([ [ Create, { - kind: 'struct', + kind: "struct", fields: [ - ['instruction', 'u8'], - ['name', 'string'], - ['house_number', 'u8'], - ['street', 'string'], - ['city', 'string'], + ["instruction", "u8"], + ["name", "string"], + ["house_number", "u8"], + ["street", "string"], + ["city", "string"], ], }, ], diff --git a/basics/realloc/native/ts/instructions/index.ts b/basics/realloc/native/ts/instructions/index.ts index a0876a284..dba00c454 100644 --- a/basics/realloc/native/ts/instructions/index.ts +++ b/basics/realloc/native/ts/instructions/index.ts @@ -1,3 +1,3 @@ -export * from './create'; -export * from './instruction'; -export * from './reallocate'; +export * from "./create"; +export * from "./instruction"; +export * from "./reallocate"; diff --git a/basics/realloc/native/ts/instructions/reallocate.ts b/basics/realloc/native/ts/instructions/reallocate.ts index 884872d26..197e711d6 100644 --- a/basics/realloc/native/ts/instructions/reallocate.ts +++ b/basics/realloc/native/ts/instructions/reallocate.ts @@ -1,7 +1,7 @@ -import { Buffer } from 'node:buffer'; -import { type PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { ReallocInstruction } from './instruction'; +import { Buffer } from "node:buffer"; +import { type PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { ReallocInstruction } from "./instruction"; export class ReallocateWithoutZeroInit { instruction: ReallocInstruction; @@ -31,11 +31,11 @@ export const ReallocateWithoutZeroInitSchema = new Map([ [ ReallocateWithoutZeroInit, { - kind: 'struct', + kind: "struct", fields: [ - ['instruction', 'u8'], - ['state', 'string'], - ['zip', 'u32'], + ["instruction", "u8"], + ["state", "string"], + ["zip", "u32"], ], }, ], @@ -101,13 +101,13 @@ export const ReallocateZeroInitSchema = new Map([ [ ReallocateZeroInit, { - kind: 'struct', + kind: "struct", fields: [ - ['instruction', 'u8'], - ['name', 'string'], - ['position', 'string'], - ['company', 'string'], - ['years_employed', 'u8'], + ["instruction", "u8"], + ["name", "string"], + ["position", "string"], + ["company", "string"], + ["years_employed", "u8"], ], }, ], diff --git a/basics/realloc/native/ts/state/address-info.ts b/basics/realloc/native/ts/state/address-info.ts index d3a3e466f..6acf96c8a 100644 --- a/basics/realloc/native/ts/state/address-info.ts +++ b/basics/realloc/native/ts/state/address-info.ts @@ -1,5 +1,5 @@ -import { Buffer } from 'node:buffer'; -import * as borsh from 'borsh'; +import { Buffer } from "node:buffer"; +import * as borsh from "borsh"; export class AddressInfo { name: string; @@ -36,12 +36,12 @@ export const AddressInfoSchema = new Map([ [ AddressInfo, { - kind: 'struct', + kind: "struct", fields: [ - ['name', 'string'], - ['house_number', 'u8'], - ['street', 'string'], - ['city', 'string'], + ["name", "string"], + ["house_number", "u8"], + ["street", "string"], + ["city", "string"], ], }, ], diff --git a/basics/realloc/native/ts/state/enhanced-address-info.ts b/basics/realloc/native/ts/state/enhanced-address-info.ts index ba7f38b57..edbda7781 100644 --- a/basics/realloc/native/ts/state/enhanced-address-info.ts +++ b/basics/realloc/native/ts/state/enhanced-address-info.ts @@ -1,5 +1,5 @@ -import { Buffer } from 'node:buffer'; -import * as borsh from 'borsh'; +import { Buffer } from "node:buffer"; +import * as borsh from "borsh"; export class EnhancedAddressInfo { name: string; @@ -42,14 +42,14 @@ export const EnhancedAddressInfoSchema = new Map([ [ EnhancedAddressInfo, { - kind: 'struct', + kind: "struct", fields: [ - ['name', 'string'], - ['house_number', 'u8'], - ['street', 'string'], - ['city', 'string'], - ['state', 'string'], - ['zip', 'u32'], + ["name", "string"], + ["house_number", "u8"], + ["street", "string"], + ["city", "string"], + ["state", "string"], + ["zip", "u32"], ], }, ], diff --git a/basics/realloc/native/ts/state/index.ts b/basics/realloc/native/ts/state/index.ts index 5b4330eb5..2cc8c6587 100644 --- a/basics/realloc/native/ts/state/index.ts +++ b/basics/realloc/native/ts/state/index.ts @@ -1,3 +1,3 @@ -export * from './address-info'; -export * from './enhanced-address-info'; -export * from './work-info'; +export * from "./address-info"; +export * from "./enhanced-address-info"; +export * from "./work-info"; diff --git a/basics/realloc/native/ts/state/work-info.ts b/basics/realloc/native/ts/state/work-info.ts index 8275ba017..26a89ebec 100644 --- a/basics/realloc/native/ts/state/work-info.ts +++ b/basics/realloc/native/ts/state/work-info.ts @@ -1,5 +1,5 @@ -import { Buffer } from 'node:buffer'; -import * as borsh from 'borsh'; +import { Buffer } from "node:buffer"; +import * as borsh from "borsh"; export class WorkInfo { name: string; @@ -36,12 +36,12 @@ export const WorkInfoSchema = new Map([ [ WorkInfo, { - kind: 'struct', + kind: "struct", fields: [ - ['name', 'string'], - ['position', 'string'], - ['company', 'string'], - ['years_employed', 'u8'], + ["name", "string"], + ["position", "string"], + ["company", "string"], + ["years_employed", "u8"], ], }, ], diff --git a/basics/realloc/native/ts/util/index.ts b/basics/realloc/native/ts/util/index.ts index bbebd88eb..181e76f24 100644 --- a/basics/realloc/native/ts/util/index.ts +++ b/basics/realloc/native/ts/util/index.ts @@ -1 +1 @@ -export * from './util'; +export * from "./util"; diff --git a/basics/realloc/native/ts/util/util.ts b/basics/realloc/native/ts/util/util.ts index 0e63c77df..7e72414f8 100644 --- a/basics/realloc/native/ts/util/util.ts +++ b/basics/realloc/native/ts/util/util.ts @@ -1,5 +1,5 @@ -import { Keypair } from '@solana/web3.js'; +import { Keypair } from "@solana/web3.js"; export function createKeypairFromFile(path: string): Keypair { - return Keypair.fromSecretKey(Buffer.from(JSON.parse(require('node:fs').readFileSync(path, 'utf-8')))); + return Keypair.fromSecretKey(Buffer.from(JSON.parse(require("node:fs").readFileSync(path, "utf-8")))); } diff --git a/basics/realloc/pinocchio/program/Cargo.toml b/basics/realloc/pinocchio/program/Cargo.toml index 0a475abf2..35d0043d1 100644 --- a/basics/realloc/pinocchio/program/Cargo.toml +++ b/basics/realloc/pinocchio/program/Cargo.toml @@ -20,7 +20,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/realloc/pinocchio/tests/realloc.test.ts b/basics/realloc/pinocchio/tests/realloc.test.ts index 58b2b4fb5..4d32049cf 100644 --- a/basics/realloc/pinocchio/tests/realloc.test.ts +++ b/basics/realloc/pinocchio/tests/realloc.test.ts @@ -1,6 +1,4 @@ -import { describe, test } from "node:test"; -import { Keypair, PublicKey, Transaction } from "@solana/web3.js"; -import { start } from "solana-bankrun"; +import { describe } from "node:test"; describe("Realloc!", async () => { console.log("Realloc!"); diff --git a/basics/rent/anchor/Anchor.toml b/basics/rent/anchor/Anchor.toml index 89a73d190..aa67963df 100644 --- a/basics/rent/anchor/Anchor.toml +++ b/basics/rent/anchor/Anchor.toml @@ -2,15 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false -[programs.localnet] -rent_example = "ED6f4gweAE7hWPQPXMt4kWxzDJne8VQEm9zkb1tMpFNB" +resolution = true +skip-lint = false -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +rent_example = "3efkmFTva1SZmFPt7E2nTe6SkCLUfuzayXgfjsMJr5Ac" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/rent/anchor/package.json b/basics/rent/anchor/package.json index 0696e9344..878e62db1 100644 --- a/basics/rent/anchor/package.json +++ b/basics/rent/anchor/package.json @@ -1,17 +1,17 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/rent/anchor/pnpm-lock.yaml b/basics/rent/anchor/pnpm-lock.yaml index a1b80e5e9..f30ff0b8a 100644 --- a/basics/rent/anchor/pnpm-lock.yaml +++ b/basics/rent/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': @@ -758,16 +758,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -785,7 +785,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: diff --git a/basics/rent/anchor/programs/rent-example/Cargo.toml b/basics/rent/anchor/programs/rent-example/Cargo.toml index 648979a7b..1561b91b1 100644 --- a/basics/rent/anchor/programs/rent-example/Cargo.toml +++ b/basics/rent/anchor/programs/rent-example/Cargo.toml @@ -20,8 +20,14 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/rent/anchor/programs/rent-example/src/lib.rs b/basics/rent/anchor/programs/rent-example/src/lib.rs index a16dcd071..02cc0215a 100644 --- a/basics/rent/anchor/programs/rent-example/src/lib.rs +++ b/basics/rent/anchor/programs/rent-example/src/lib.rs @@ -1,7 +1,7 @@ use anchor_lang::prelude::*; use anchor_lang::system_program; -declare_id!("ED6f4gweAE7hWPQPXMt4kWxzDJne8VQEm9zkb1tMpFNB"); +declare_id!("3efkmFTva1SZmFPt7E2nTe6SkCLUfuzayXgfjsMJr5Ac"); #[program] pub mod rent_example { diff --git a/basics/rent/anchor/programs/rent-example/tests/test_rent.rs b/basics/rent/anchor/programs/rent-example/tests/test_rent.rs new file mode 100644 index 000000000..447a1ad0b --- /dev/null +++ b/basics/rent/anchor/programs/rent-example/tests/test_rent.rs @@ -0,0 +1,76 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, system_program}, + InstructionData, ToAccountMetas, + }, + borsh::BorshDeserialize, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +/// Build borsh-serialized AddressData bytes (fields are private in the crate). +fn build_address_data_borsh(name: &str, address: &str) -> Vec { + let mut data = Vec::new(); + data.extend_from_slice(&(name.len() as u32).to_le_bytes()); + data.extend_from_slice(name.as_bytes()); + data.extend_from_slice(&(address.len() as u32).to_le_bytes()); + data.extend_from_slice(address.as_bytes()); + data +} + +/// Construct the full instruction data with discriminator + AddressData. +/// Deserialize the borsh bytes into AddressData via the crate's BorshDeserialize impl, +/// then use InstructionData to get the final bytes. +fn build_create_system_account_ix_data(name: &str, address: &str) -> Vec { + let address_data_bytes = build_address_data_borsh(name, address); + let address_data = + rent_example::AddressData::deserialize(&mut address_data_bytes.as_slice()).unwrap(); + rent_example::instruction::CreateSystemAccount { address_data }.data() +} + +#[test] +fn test_create_system_account() { + let program_id = rent_example::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/rent_example.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let new_account = Keypair::new(); + + let name = "Marcus"; + let address = "123 Main St. San Francisco, CA"; + + let ix_data = build_create_system_account_ix_data(name, address); + + let instruction = Instruction::new_with_bytes( + program_id, + &ix_data, + rent_example::accounts::CreateSystemAccount { + payer: payer.pubkey(), + new_account: new_account.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &new_account], + &payer.pubkey(), + ) + .unwrap(); + + // Verify the account was created with the correct size + // Borsh serialized AddressData: 4 + 6 ("Marcus") + 4 + 30 = 44 bytes + let expected_size = 4 + name.len() + 4 + address.len(); + let account = svm.get_account(&new_account.pubkey()).unwrap(); + assert_eq!(account.data.len(), expected_size); + assert!( + account.lamports > 0, + "Account should have lamports for rent" + ); +} diff --git a/basics/rent/anchor/tests/litesvm.test.ts b/basics/rent/anchor/tests/litesvm.test.ts index b102af9f0..c289d1e8a 100644 --- a/basics/rent/anchor/tests/litesvm.test.ts +++ b/basics/rent/anchor/tests/litesvm.test.ts @@ -1,74 +1,68 @@ import anchor from "@anchor-lang/core"; import { - Keypair, - LAMPORTS_PER_SOL, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, + Keypair, + LAMPORTS_PER_SOL, + PublicKey, + SystemProgram, + Transaction, + TransactionInstruction, } from "@solana/web3.js"; import { assert } from "chai"; import { LiteSVM } from "litesvm"; import Idl from "../target/idl/rent_example.json" with { type: "json" }; describe("LiteSVM: Create a system account", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(Idl.address); - const coder = new anchor.BorshCoder(Idl as anchor.Idl); + const svm = new LiteSVM(); + const programId = new PublicKey(Idl.address); + const coder = new anchor.BorshCoder(Idl as anchor.Idl); - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(2 * LAMPORTS_PER_SOL)); + const payer = Keypair.generate(); + svm.airdrop(payer.publicKey, BigInt(2 * LAMPORTS_PER_SOL)); - const programPath = new URL( - "../target/deploy/rent_example.so", - import.meta.url, - ).pathname; - svm.addProgramFromFile(programId, programPath); + const programPath = new URL("../target/deploy/rent_example.so", import.meta.url).pathname; + svm.addProgramFromFile(programId, programPath); - it("Create the account", () => { - const newKeypair = Keypair.generate(); + it("Create the account", () => { + const newKeypair = Keypair.generate(); - const ixArgs = { - address_data: { - name: "Marcus", - address: "123 Main St. San Francisco, CA", - }, - }; + const ixArgs = { + address_data: { + name: "Marcus", + address: "123 Main St. San Francisco, CA", + }, + }; - /** - * Create Instructions - * Create Transactions - * Send Transactions - */ - const data = coder.instruction.encode("create_system_account", ixArgs); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: newKeypair.publicKey, isSigner: true, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); + /** + * Create Instructions + * Create Transactions + * Send Transactions + */ + const data = coder.instruction.encode("create_system_account", ixArgs); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: newKeypair.publicKey, isSigner: true, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer, newKeypair); - svm.sendTransaction(tx); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer, newKeypair); + svm.sendTransaction(tx); - /** - * We're just going to serialize our object here so we can check - * the size on the client side against the program logs - */ - const addressDataBuffer = coder.types.encode( - "AddressData", - ixArgs.address_data, - ); + /** + * We're just going to serialize our object here so we can check + * the size on the client side against the program logs + */ + const addressDataBuffer = coder.types.encode("AddressData", ixArgs.address_data); - //Fetch newKeypair account and check its rent for space - const newKeypairInfo = svm.getAccount(newKeypair.publicKey); + //Fetch newKeypair account and check its rent for space + const newKeypairInfo = svm.getAccount(newKeypair.publicKey); - assert.equal(newKeypairInfo.data.length, addressDataBuffer.length); - }); + assert.equal(newKeypairInfo.data.length, addressDataBuffer.length); + }); }); diff --git a/basics/rent/anchor/tests/test.ts b/basics/rent/anchor/tests/test.ts index 7755d3d47..fdea57a3a 100644 --- a/basics/rent/anchor/tests/test.ts +++ b/basics/rent/anchor/tests/test.ts @@ -4,39 +4,35 @@ import Idl from "../target/idl/rent_example.json" with { type: "json" }; import type { RentExample } from "../target/types/rent_example.ts"; describe("Anchor: Create a system account", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const wallet = provider.wallet as anchor.Wallet; - const program = anchor.workspace.RentExample as anchor.Program; + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const wallet = provider.wallet as anchor.Wallet; + const program = anchor.workspace.RentExample as anchor.Program; - it("Create the account", async () => { - const newKeypair = anchor.web3.Keypair.generate(); + it("Create the account", async () => { + const newKeypair = anchor.web3.Keypair.generate(); - const addressData: anchor.IdlTypes["addressData"] = { - name: "Marcus", - address: "123 Main St. San Francisco, CA", - }; + const addressData: anchor.IdlTypes["addressData"] = { + name: "Marcus", + address: "123 Main St. San Francisco, CA", + }; - // We're just going to serialize our object here so we can check - // the size on the client side against the program logs - // - const addressDataBuffer = new anchor.BorshCoder( - Idl as anchor.Idl, - ).types.encode("AddressData", addressData); + // We're just going to serialize our object here so we can check + // the size on the client side against the program logs + // + const addressDataBuffer = new anchor.BorshCoder(Idl as anchor.Idl).types.encode("AddressData", addressData); - await program.methods - .createSystemAccount(addressData) - .accounts({ - payer: wallet.publicKey, - newAccount: newKeypair.publicKey, - }) - .signers([wallet.payer, newKeypair]) - .rpc(); + await program.methods + .createSystemAccount(addressData) + .accounts({ + payer: wallet.publicKey, + newAccount: newKeypair.publicKey, + }) + .signers([wallet.payer, newKeypair]) + .rpc(); - const newKeypairInfo = await provider.connection.getAccountInfo( - newKeypair.publicKey, - ); + const newKeypairInfo = await provider.connection.getAccountInfo(newKeypair.publicKey); - assert.equal(newKeypairInfo.data.length, addressDataBuffer.length); - }); + assert.equal(newKeypairInfo.data.length, addressDataBuffer.length); + }); }); diff --git a/basics/rent/anchor/tsconfig.json b/basics/rent/anchor/tsconfig.json index 59fe75cf0..beb254c00 100644 --- a/basics/rent/anchor/tsconfig.json +++ b/basics/rent/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], - "module": "nodenext", - "target": "es6", - "esModuleInterop": true - } + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "nodenext", + "target": "es6", + "esModuleInterop": true + } } diff --git a/basics/rent/native/program/Cargo.toml b/basics/rent/native/program/Cargo.toml index 018875285..dcbff7dc9 100644 --- a/basics/rent/native/program/Cargo.toml +++ b/basics/rent/native/program/Cargo.toml @@ -20,7 +20,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/rent/native/tests/test.ts b/basics/rent/native/tests/test.ts index b07f32f79..1dc1fdee9 100644 --- a/basics/rent/native/tests/test.ts +++ b/basics/rent/native/tests/test.ts @@ -1,19 +1,19 @@ -import { Buffer } from 'node:buffer'; -import { describe, test } from 'node:test'; -import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { start } from 'solana-bankrun'; +import { Buffer } from "node:buffer"; +import { describe, test } from "node:test"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { start } from "solana-bankrun"; -describe('Create a system account', async () => { +describe("Create a system account", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; const AddressDataSchema = { struct: { - name: 'string', - address: 'string', + name: "string", + address: "string", }, }; @@ -21,12 +21,12 @@ describe('Create a system account', async () => { return Buffer.from(borsh.serialize(schema, data)); } - test('Create the account', async () => { + test("Create the account", async () => { const newKeypair = Keypair.generate(); const addressData = { - name: 'Marcus', - address: '123 Main St. San Francisco, CA', + name: "Marcus", + address: "123 Main St. San Francisco, CA", }; // We're just going to serialize our object here so we can check diff --git a/basics/rent/pinocchio/program/Cargo.toml b/basics/rent/pinocchio/program/Cargo.toml index f58109e0b..486190ede 100644 --- a/basics/rent/pinocchio/program/Cargo.toml +++ b/basics/rent/pinocchio/program/Cargo.toml @@ -19,7 +19,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/rent/pinocchio/tests/test.ts b/basics/rent/pinocchio/tests/test.ts index ad53cf096..4c97d9a1b 100644 --- a/basics/rent/pinocchio/tests/test.ts +++ b/basics/rent/pinocchio/tests/test.ts @@ -1,5 +1,4 @@ -import { Buffer } from "node:buffer"; -import { describe, test } from "node:test"; +import { describe } from "node:test"; describe("Create a system account", async () => { console.log("Create a system account"); diff --git a/basics/repository-layout/anchor/Anchor.toml b/basics/repository-layout/anchor/Anchor.toml index 8d4faedce..62791d317 100644 --- a/basics/repository-layout/anchor/Anchor.toml +++ b/basics/repository-layout/anchor/Anchor.toml @@ -2,15 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false -[programs.localnet] -carnival = "8t94SEJh9jVjDwV7cbiuT6BvEsHo4YHP9x9a5rYH1NpP" +resolution = true +skip-lint = false -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +carnival = "FY78H521JC85fwffNHeV5BjKvhvRVuVtFgVrick7JEQj" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/repository-layout/anchor/package.json b/basics/repository-layout/anchor/package.json index 0696e9344..878e62db1 100644 --- a/basics/repository-layout/anchor/package.json +++ b/basics/repository-layout/anchor/package.json @@ -1,17 +1,17 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/repository-layout/anchor/pnpm-lock.yaml b/basics/repository-layout/anchor/pnpm-lock.yaml index ddb089051..8b77b2a35 100644 --- a/basics/repository-layout/anchor/pnpm-lock.yaml +++ b/basics/repository-layout/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': @@ -755,16 +755,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -782,7 +782,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: diff --git a/basics/repository-layout/anchor/programs/carnival/Cargo.toml b/basics/repository-layout/anchor/programs/carnival/Cargo.toml index 71a3df21d..6708568ec 100644 --- a/basics/repository-layout/anchor/programs/carnival/Cargo.toml +++ b/basics/repository-layout/anchor/programs/carnival/Cargo.toml @@ -20,8 +20,13 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/repository-layout/anchor/programs/carnival/src/lib.rs b/basics/repository-layout/anchor/programs/carnival/src/lib.rs index 9a9269e6b..7cc752a84 100644 --- a/basics/repository-layout/anchor/programs/carnival/src/lib.rs +++ b/basics/repository-layout/anchor/programs/carnival/src/lib.rs @@ -8,7 +8,7 @@ use crate::instructions::{eat_food, get_on_ride, play_game}; // For setting up modules & configs -declare_id!("8t94SEJh9jVjDwV7cbiuT6BvEsHo4YHP9x9a5rYH1NpP"); +declare_id!("FY78H521JC85fwffNHeV5BjKvhvRVuVtFgVrick7JEQj"); #[program] pub mod carnival { diff --git a/basics/repository-layout/anchor/programs/carnival/tests/test_carnival.rs b/basics/repository-layout/anchor/programs/carnival/tests/test_carnival.rs new file mode 100644 index 000000000..ff2221246 --- /dev/null +++ b/basics/repository-layout/anchor/programs/carnival/tests/test_carnival.rs @@ -0,0 +1,115 @@ +use { + anchor_lang::{solana_program::instruction::Instruction, InstructionData, ToAccountMetas}, + litesvm::LiteSVM, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, solana_keypair::Keypair) { + let program_id = carnival::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/carnival.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, payer) +} + +#[test] +fn test_go_on_rides() { + let (mut svm, payer) = setup(); + + let accounts = carnival::accounts::CarnivalContext { + payer: payer.pubkey(), + } + .to_account_metas(None); + + let instructions: Vec = vec![ + ("Jimmy", 36u32, 15u32, "Scrambler"), + ("Mary", 52, 1, "Ferris Wheel"), + ("Alice", 56, 15, "Scrambler"), + ("Bob", 49, 6, "Tilt-a-Whirl"), + ] + .into_iter() + .map(|(name, height, tickets, ride)| { + Instruction::new_with_bytes( + carnival::id(), + &carnival::instruction::GoOnRide { + name: name.to_string(), + height, + ticket_count: tickets, + ride_name: ride.to_string(), + } + .data(), + accounts.clone(), + ) + }) + .collect(); + + send_transaction_from_instructions(&mut svm, instructions, &[&payer], &payer.pubkey()).unwrap(); +} + +#[test] +fn test_play_games() { + let (mut svm, payer) = setup(); + + let accounts = carnival::accounts::CarnivalContext { + payer: payer.pubkey(), + } + .to_account_metas(None); + + let instructions: Vec = vec![ + ("Jimmy", 15u32, "I Got It!"), + ("Mary", 1, "Ring Toss"), + ("Alice", 15, "Ladder Climb"), + ("Bob", 6, "Ring Toss"), + ] + .into_iter() + .map(|(name, tickets, game)| { + Instruction::new_with_bytes( + carnival::id(), + &carnival::instruction::PlayGame { + name: name.to_string(), + ticket_count: tickets, + game_name: game.to_string(), + } + .data(), + accounts.clone(), + ) + }) + .collect(); + + send_transaction_from_instructions(&mut svm, instructions, &[&payer], &payer.pubkey()).unwrap(); +} + +#[test] +fn test_eat_food() { + let (mut svm, payer) = setup(); + + let accounts = carnival::accounts::CarnivalContext { + payer: payer.pubkey(), + } + .to_account_metas(None); + + let instructions: Vec = vec![ + ("Jimmy", 15u32, "Taco Shack"), + ("Mary", 1, "Larry's Pizza"), + ("Alice", 15, "Dough Boy's"), + ("Bob", 6, "Dough Boy's"), + ] + .into_iter() + .map(|(name, tickets, food_stand)| { + Instruction::new_with_bytes( + carnival::id(), + &carnival::instruction::EatFood { + name: name.to_string(), + ticket_count: tickets, + food_stand_name: food_stand.to_string(), + } + .data(), + accounts.clone(), + ) + }) + .collect(); + + send_transaction_from_instructions(&mut svm, instructions, &[&payer], &payer.pubkey()).unwrap(); +} diff --git a/basics/repository-layout/anchor/tests/litesvm.test.ts b/basics/repository-layout/anchor/tests/litesvm.test.ts index a77a18431..96bbc11a0 100644 --- a/basics/repository-layout/anchor/tests/litesvm.test.ts +++ b/basics/repository-layout/anchor/tests/litesvm.test.ts @@ -1,129 +1,119 @@ import anchor from "@anchor-lang/core"; -import { - Keypair, - LAMPORTS_PER_SOL, - PublicKey, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, LAMPORTS_PER_SOL, PublicKey, Transaction, TransactionInstruction } from "@solana/web3.js"; import { LiteSVM } from "litesvm"; import Idl from "../target/idl/carnival.json" with { type: "json" }; describe("LiteSVM: Carnival", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(Idl.address); - const coder = new anchor.BorshCoder(Idl as anchor.Idl); - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(5 * LAMPORTS_PER_SOL)); + const svm = new LiteSVM(); + const programId = new PublicKey(Idl.address); + const coder = new anchor.BorshCoder(Idl as anchor.Idl); + const payer = Keypair.generate(); + svm.airdrop(payer.publicKey, BigInt(5 * LAMPORTS_PER_SOL)); - const programPath = new URL("../target/deploy/carnival.so", import.meta.url) - .pathname; - svm.addProgramFromFile(programId, programPath); + const programPath = new URL("../target/deploy/carnival.so", import.meta.url).pathname; + svm.addProgramFromFile(programId, programPath); - it("Go on some rides!", () => { - const jimmyIxArgs = { - name: "Jimmy", - height: 36, - ticket_count: 15, - ride_name: "Scrambler", - }; - const maryIxArgs = { - name: "Mary", - height: 52, - ticket_count: 1, - ride_name: "Ferris Wheel", - }; - const bobIxArgs = { - name: "Alice", - height: 56, - ticket_count: 15, - ride_name: "Scrambler", - }; - const aliceIxArgs = { - name: "Bob", - height: 49, - ticket_count: 6, - ride_name: "Tilt-a-Whirl", - }; + it("Go on some rides!", () => { + const jimmyIxArgs = { + name: "Jimmy", + height: 36, + ticket_count: 15, + ride_name: "Scrambler", + }; + const maryIxArgs = { + name: "Mary", + height: 52, + ticket_count: 1, + ride_name: "Ferris Wheel", + }; + const bobIxArgs = { + name: "Alice", + height: 56, + ticket_count: 15, + ride_name: "Scrambler", + }; + const aliceIxArgs = { + name: "Bob", + height: 49, + ticket_count: 6, + ride_name: "Tilt-a-Whirl", + }; - createAndSendTx(jimmyIxArgs, "go_on_ride"); - createAndSendTx(maryIxArgs, "go_on_ride"); - createAndSendTx(bobIxArgs, "go_on_ride"); - createAndSendTx(aliceIxArgs, "go_on_ride"); - }); + createAndSendTx(jimmyIxArgs, "go_on_ride"); + createAndSendTx(maryIxArgs, "go_on_ride"); + createAndSendTx(bobIxArgs, "go_on_ride"); + createAndSendTx(aliceIxArgs, "go_on_ride"); + }); - it("Play some games!", () => { - const jimmyIxArgs = { - name: "Jimmy", - ticket_count: 15, - game_name: "I Got It!", - }; - const maryIxArgs = { - name: "Mary", - ticket_count: 1, - game_name: "Ring Toss", - }; - const aliceIxArgs = { - name: "Alice", - ticket_count: 15, - game_name: "Ladder Climb", - }; - const bobIxArgs = { - name: "Bob", - ticket_count: 6, - game_name: "Ring Toss", - }; + it("Play some games!", () => { + const jimmyIxArgs = { + name: "Jimmy", + ticket_count: 15, + game_name: "I Got It!", + }; + const maryIxArgs = { + name: "Mary", + ticket_count: 1, + game_name: "Ring Toss", + }; + const aliceIxArgs = { + name: "Alice", + ticket_count: 15, + game_name: "Ladder Climb", + }; + const bobIxArgs = { + name: "Bob", + ticket_count: 6, + game_name: "Ring Toss", + }; - createAndSendTx(jimmyIxArgs, "play_game"); - createAndSendTx(maryIxArgs, "play_game"); - createAndSendTx(aliceIxArgs, "play_game"); - createAndSendTx(bobIxArgs, "play_game"); - }); + createAndSendTx(jimmyIxArgs, "play_game"); + createAndSendTx(maryIxArgs, "play_game"); + createAndSendTx(aliceIxArgs, "play_game"); + createAndSendTx(bobIxArgs, "play_game"); + }); - it("Eat some food!", () => { - const jimmyIxArgs = { - name: "Jimmy", - ticket_count: 15, - food_stand_name: "Taco Shack", - }; - const maryIxArgs = { - name: "Mary", - ticket_count: 1, - food_stand_name: "Larry's Pizza", - }; - const aliceIxArgs = { - name: "Alice", - ticket_count: 15, - food_stand_name: "Dough Boy's", - }; - const bobIxArgs = { - name: "Bob", - ticket_count: 6, - food_stand_name: "Dough Boy's", - }; + it("Eat some food!", () => { + const jimmyIxArgs = { + name: "Jimmy", + ticket_count: 15, + food_stand_name: "Taco Shack", + }; + const maryIxArgs = { + name: "Mary", + ticket_count: 1, + food_stand_name: "Larry's Pizza", + }; + const aliceIxArgs = { + name: "Alice", + ticket_count: 15, + food_stand_name: "Dough Boy's", + }; + const bobIxArgs = { + name: "Bob", + ticket_count: 6, + food_stand_name: "Dough Boy's", + }; - createAndSendTx(jimmyIxArgs, "eat_food"); - createAndSendTx(maryIxArgs, "eat_food"); - createAndSendTx(aliceIxArgs, "eat_food"); - createAndSendTx(bobIxArgs, "eat_food"); - }); + createAndSendTx(jimmyIxArgs, "eat_food"); + createAndSendTx(maryIxArgs, "eat_food"); + createAndSendTx(aliceIxArgs, "eat_food"); + createAndSendTx(bobIxArgs, "eat_food"); + }); - function createAndSendTx( - ixArgs: Record, - ixName: string, - ) { - const data = coder.instruction.encode(ixName, ixArgs); - const ix = new TransactionInstruction({ - keys: [{ pubkey: payer.publicKey, isSigner: true, isWritable: true }], - programId, - data, - }); + function createAndSendTx(ixArgs: Record, ixName: string) { + const data = coder.instruction.encode(ixName, ixArgs); + const ix = new TransactionInstruction({ + keys: [{ pubkey: payer.publicKey, isSigner: true, isWritable: true }], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - const re = svm.sendTransaction(tx); - // console.log(re.toString()); - } + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + const _re = svm.sendTransaction(tx); + // console.log(re.toString()); + } }); diff --git a/basics/repository-layout/anchor/tests/test.ts b/basics/repository-layout/anchor/tests/test.ts index 497a11edd..2d978110a 100644 --- a/basics/repository-layout/anchor/tests/test.ts +++ b/basics/repository-layout/anchor/tests/test.ts @@ -2,55 +2,43 @@ import * as anchor from "@anchor-lang/core"; import type { Carnival } from "../target/types/carnival.ts"; describe("Carnival", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const wallet = provider.wallet as anchor.Wallet; - const program = anchor.workspace.Carnival as anchor.Program; + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const wallet = provider.wallet as anchor.Wallet; + const program = anchor.workspace.Carnival as anchor.Program; - async function sendCarnivalInstructions( - instructionsList: anchor.web3.TransactionInstruction[], - ) { - const tx = new anchor.web3.Transaction(); - for (const ix of instructionsList) { - tx.add(ix); - } - await anchor.web3.sendAndConfirmTransaction(provider.connection, tx, [ - wallet.payer, - ]); - } + async function sendCarnivalInstructions(instructionsList: anchor.web3.TransactionInstruction[]) { + const tx = new anchor.web3.Transaction(); + for (const ix of instructionsList) { + tx.add(ix); + } + await anchor.web3.sendAndConfirmTransaction(provider.connection, tx, [wallet.payer]); + } - it("Go on some rides!", async () => { - await sendCarnivalInstructions([ - await program.methods - .goOnRide("Jimmy", 36, 15, "Scrambler") - .instruction(), - await program.methods - .goOnRide("Mary", 52, 1, "Ferris Wheel") - .instruction(), - await program.methods - .goOnRide("Alice", 56, 15, "Scrambler") - .instruction(), - await program.methods - .goOnRide("Bob", 49, 6, "Tilt-a-Whirl") - .instruction(), - ]); - }); + it("Go on some rides!", async () => { + await sendCarnivalInstructions([ + await program.methods.goOnRide("Jimmy", 36, 15, "Scrambler").instruction(), + await program.methods.goOnRide("Mary", 52, 1, "Ferris Wheel").instruction(), + await program.methods.goOnRide("Alice", 56, 15, "Scrambler").instruction(), + await program.methods.goOnRide("Bob", 49, 6, "Tilt-a-Whirl").instruction(), + ]); + }); - it("Play some games!", async () => { - await sendCarnivalInstructions([ - await program.methods.playGame("Jimmy", 15, "I Got It!").instruction(), - await program.methods.playGame("Mary", 1, "Ring Toss").instruction(), - await program.methods.playGame("Alice", 15, "Ladder Climb").instruction(), - await program.methods.playGame("Bob", 6, "Ring Toss").instruction(), - ]); - }); + it("Play some games!", async () => { + await sendCarnivalInstructions([ + await program.methods.playGame("Jimmy", 15, "I Got It!").instruction(), + await program.methods.playGame("Mary", 1, "Ring Toss").instruction(), + await program.methods.playGame("Alice", 15, "Ladder Climb").instruction(), + await program.methods.playGame("Bob", 6, "Ring Toss").instruction(), + ]); + }); - it("Eat some food!", async () => { - await sendCarnivalInstructions([ - await program.methods.eatFood("Jimmy", 15, "Taco Shack").instruction(), - await program.methods.eatFood("Mary", 1, "Larry's Pizza").instruction(), - await program.methods.eatFood("Alice", 15, "Dough Boy's").instruction(), - await program.methods.eatFood("Bob", 6, "Dough Boy's").instruction(), - ]); - }); + it("Eat some food!", async () => { + await sendCarnivalInstructions([ + await program.methods.eatFood("Jimmy", 15, "Taco Shack").instruction(), + await program.methods.eatFood("Mary", 1, "Larry's Pizza").instruction(), + await program.methods.eatFood("Alice", 15, "Dough Boy's").instruction(), + await program.methods.eatFood("Bob", 6, "Dough Boy's").instruction(), + ]); + }); }); diff --git a/basics/repository-layout/anchor/tsconfig.json b/basics/repository-layout/anchor/tsconfig.json index 59fe75cf0..beb254c00 100644 --- a/basics/repository-layout/anchor/tsconfig.json +++ b/basics/repository-layout/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], - "module": "nodenext", - "target": "es6", - "esModuleInterop": true - } + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "nodenext", + "target": "es6", + "esModuleInterop": true + } } diff --git a/basics/repository-layout/native/program/Cargo.toml b/basics/repository-layout/native/program/Cargo.toml index 049e72758..61290f9ff 100644 --- a/basics/repository-layout/native/program/Cargo.toml +++ b/basics/repository-layout/native/program/Cargo.toml @@ -19,7 +19,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/repository-layout/native/tests/test.ts b/basics/repository-layout/native/tests/test.ts index db8b6dedd..d480899ff 100644 --- a/basics/repository-layout/native/tests/test.ts +++ b/basics/repository-layout/native/tests/test.ts @@ -1,22 +1,22 @@ -import { Buffer } from 'node:buffer'; -import { describe, test } from 'node:test'; -import { PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { start } from 'solana-bankrun'; +import { Buffer } from "node:buffer"; +import { describe, test } from "node:test"; +import { PublicKey, Transaction, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { start } from "solana-bankrun"; -describe('Carnival', async () => { +describe("Carnival", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'repository_layout_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "repository_layout_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; const CarnivalInstructionSchema = { struct: { - name: 'string', - height: 'u32', - ticket_count: 'u32', - attraction: 'string', - attraction_name: 'string', + name: "string", + height: "u32", + ticket_count: "u32", + attraction: "string", + attraction_name: "string", }, }; @@ -47,30 +47,102 @@ describe('Carnival', async () => { await client.processTransaction(tx); } - test('Go on some rides!', async () => { + test("Go on some rides!", async () => { await sendCarnivalInstructions([ - { name: 'Jimmy', height: 36, ticket_count: 15, attraction: 'ride', attraction_name: 'Scrambler' }, - { name: 'Mary', height: 52, ticket_count: 1, attraction: 'ride', attraction_name: 'Ferris Wheel' }, - { name: 'Alice', height: 56, ticket_count: 15, attraction: 'ride', attraction_name: 'Scrambler' }, - { name: 'Bob', height: 49, ticket_count: 6, attraction: 'ride', attraction_name: 'Tilt-a-Whirl' }, + { + name: "Jimmy", + height: 36, + ticket_count: 15, + attraction: "ride", + attraction_name: "Scrambler", + }, + { + name: "Mary", + height: 52, + ticket_count: 1, + attraction: "ride", + attraction_name: "Ferris Wheel", + }, + { + name: "Alice", + height: 56, + ticket_count: 15, + attraction: "ride", + attraction_name: "Scrambler", + }, + { + name: "Bob", + height: 49, + ticket_count: 6, + attraction: "ride", + attraction_name: "Tilt-a-Whirl", + }, ]); }); - test('Play some games!', async () => { + test("Play some games!", async () => { await sendCarnivalInstructions([ - { name: 'Jimmy', height: 36, ticket_count: 15, attraction: 'game', attraction_name: 'I Got It!' }, - { name: 'Mary', height: 52, ticket_count: 1, attraction: 'game', attraction_name: 'Ring Toss' }, - { name: 'Alice', height: 56, ticket_count: 15, attraction: 'game', attraction_name: 'Ladder Climb' }, - { name: 'Bob', height: 49, ticket_count: 6, attraction: 'game', attraction_name: 'Ring Toss' }, + { + name: "Jimmy", + height: 36, + ticket_count: 15, + attraction: "game", + attraction_name: "I Got It!", + }, + { + name: "Mary", + height: 52, + ticket_count: 1, + attraction: "game", + attraction_name: "Ring Toss", + }, + { + name: "Alice", + height: 56, + ticket_count: 15, + attraction: "game", + attraction_name: "Ladder Climb", + }, + { + name: "Bob", + height: 49, + ticket_count: 6, + attraction: "game", + attraction_name: "Ring Toss", + }, ]); }); - test('Eat some food!', async () => { + test("Eat some food!", async () => { await sendCarnivalInstructions([ - { name: 'Jimmy', height: 36, ticket_count: 15, attraction: 'food', attraction_name: 'Taco Shack' }, - { name: 'Mary', height: 52, ticket_count: 1, attraction: 'food', attraction_name: "Larry's Pizza" }, - { name: 'Alice', height: 56, ticket_count: 15, attraction: 'food', attraction_name: "Dough Boy's" }, - { name: 'Bob', height: 49, ticket_count: 6, attraction: 'food', attraction_name: "Dough Boy's" }, + { + name: "Jimmy", + height: 36, + ticket_count: 15, + attraction: "food", + attraction_name: "Taco Shack", + }, + { + name: "Mary", + height: 52, + ticket_count: 1, + attraction: "food", + attraction_name: "Larry's Pizza", + }, + { + name: "Alice", + height: 56, + ticket_count: 15, + attraction: "food", + attraction_name: "Dough Boy's", + }, + { + name: "Bob", + height: 49, + ticket_count: 6, + attraction: "food", + attraction_name: "Dough Boy's", + }, ]); }); }); diff --git a/basics/transfer-sol/anchor/Anchor.toml b/basics/transfer-sol/anchor/Anchor.toml index 7e5ef2b8f..8b0c32acc 100644 --- a/basics/transfer-sol/anchor/Anchor.toml +++ b/basics/transfer-sol/anchor/Anchor.toml @@ -2,15 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false -[programs.localnet] -transfer_sol = "4fQVnLWKKKYxtxgGn7Haw8v2g2Hzbu8K61JvWKvqAi7W" +resolution = true +skip-lint = false -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +transfer_sol = "5bz3T8zeTXMGEwVhuFBKmyZk1Wqhfs1K39kfDXnLLmwG" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/basics/transfer-sol/anchor/package.json b/basics/transfer-sol/anchor/package.json index 0696e9344..878e62db1 100644 --- a/basics/transfer-sol/anchor/package.json +++ b/basics/transfer-sol/anchor/package.json @@ -1,17 +1,17 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "litesvm": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "litesvm": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/basics/transfer-sol/anchor/pnpm-lock.yaml b/basics/transfer-sol/anchor/pnpm-lock.yaml index 37a30dda9..271bd4550 100644 --- a/basics/transfer-sol/anchor/pnpm-lock.yaml +++ b/basics/transfer-sol/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -746,16 +746,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -773,7 +773,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/basics/transfer-sol/anchor/programs/transfer-sol/Cargo.toml b/basics/transfer-sol/anchor/programs/transfer-sol/Cargo.toml index 08eb4312d..c6ea1ce73 100644 --- a/basics/transfer-sol/anchor/programs/transfer-sol/Cargo.toml +++ b/basics/transfer-sol/anchor/programs/transfer-sol/Cargo.toml @@ -20,8 +20,13 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/transfer-sol/anchor/programs/transfer-sol/src/lib.rs b/basics/transfer-sol/anchor/programs/transfer-sol/src/lib.rs index 7f8e92542..e7b67059d 100644 --- a/basics/transfer-sol/anchor/programs/transfer-sol/src/lib.rs +++ b/basics/transfer-sol/anchor/programs/transfer-sol/src/lib.rs @@ -1,7 +1,7 @@ use anchor_lang::prelude::*; use anchor_lang::system_program; -declare_id!("4fQVnLWKKKYxtxgGn7Haw8v2g2Hzbu8K61JvWKvqAi7W"); +declare_id!("5bz3T8zeTXMGEwVhuFBKmyZk1Wqhfs1K39kfDXnLLmwG"); #[program] pub mod transfer_sol { diff --git a/basics/transfer-sol/anchor/programs/transfer-sol/tests/test_transfer_sol.rs b/basics/transfer-sol/anchor/programs/transfer-sol/tests/test_transfer_sol.rs new file mode 100644 index 000000000..e94829362 --- /dev/null +++ b/basics/transfer-sol/anchor/programs/transfer-sol/tests/test_transfer_sol.rs @@ -0,0 +1,92 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +const LAMPORTS_PER_SOL: u64 = 1_000_000_000; + +#[test] +fn test_transfer_sol_with_cpi() { + let program_id = transfer_sol::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/transfer_sol.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10 * LAMPORTS_PER_SOL).unwrap(); + + let recipient = Keypair::new(); + + let instruction = Instruction::new_with_bytes( + program_id, + &transfer_sol::instruction::TransferSolWithCpi { + amount: LAMPORTS_PER_SOL, + } + .data(), + transfer_sol::accounts::TransferSolWithCpi { + payer: payer.pubkey(), + recipient: recipient.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![instruction], &[&payer], &payer.pubkey()) + .unwrap(); + + let recipient_balance = svm.get_balance(&recipient.pubkey()).unwrap(); + assert_eq!(recipient_balance, LAMPORTS_PER_SOL); +} + +#[test] +fn test_transfer_sol_with_program() { + let program_id = transfer_sol::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/transfer_sol.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10 * LAMPORTS_PER_SOL).unwrap(); + + // Create an account owned by our program with 1 SOL + let payer_account = Keypair::new(); + let create_account_ix = anchor_lang::solana_program::system_instruction::create_account( + &payer.pubkey(), + &payer_account.pubkey(), + LAMPORTS_PER_SOL, + 0, + &program_id, + ); + send_transaction_from_instructions( + &mut svm, + vec![create_account_ix], + &[&payer, &payer_account], + &payer.pubkey(), + ) + .unwrap(); + + // Now transfer SOL from the program-owned account to a recipient + svm.expire_blockhash(); + let recipient = Keypair::new(); + + let instruction = Instruction::new_with_bytes( + program_id, + &transfer_sol::instruction::TransferSolWithProgram { + amount: LAMPORTS_PER_SOL, + } + .data(), + transfer_sol::accounts::TransferSolWithProgram { + payer: payer_account.pubkey(), + recipient: recipient.pubkey(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![instruction], &[&payer], &payer.pubkey()) + .unwrap(); + + let recipient_balance = svm.get_balance(&recipient.pubkey()).unwrap(); + assert_eq!(recipient_balance, LAMPORTS_PER_SOL); +} diff --git a/basics/transfer-sol/anchor/tests/litesvm.test.ts b/basics/transfer-sol/anchor/tests/litesvm.test.ts index 536e796f6..21ced4b0d 100644 --- a/basics/transfer-sol/anchor/tests/litesvm.test.ts +++ b/basics/transfer-sol/anchor/tests/litesvm.test.ts @@ -1,99 +1,96 @@ import anchor from "@anchor-lang/core"; import { - Keypair, - LAMPORTS_PER_SOL, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, + Keypair, + LAMPORTS_PER_SOL, + PublicKey, + SystemProgram, + Transaction, + TransactionInstruction, } from "@solana/web3.js"; import { assert } from "chai"; import { LiteSVM } from "litesvm"; import Idl from "../target/idl/transfer_sol.json" with { type: "json" }; describe("LiteSVM: Transfer SOL", () => { - const svm = new LiteSVM(); - const programId = new PublicKey(Idl.address); - const coder = new anchor.BorshCoder(Idl as anchor.Idl); - const payer = Keypair.generate(); - svm.airdrop(payer.publicKey, BigInt(5 * LAMPORTS_PER_SOL)); + const svm = new LiteSVM(); + const programId = new PublicKey(Idl.address); + const coder = new anchor.BorshCoder(Idl as anchor.Idl); + const payer = Keypair.generate(); + svm.airdrop(payer.publicKey, BigInt(5 * LAMPORTS_PER_SOL)); - const programFilePath = new URL( - "../target/deploy/transfer_sol.so", - import.meta.url, - ).pathname; - svm.addProgramFromFile(programId, programFilePath); + const programFilePath = new URL("../target/deploy/transfer_sol.so", import.meta.url).pathname; + svm.addProgramFromFile(programId, programFilePath); - it("Transfer SOL with CPI", () => { - const recipient = Keypair.generate(); + it("Transfer SOL with CPI", () => { + const recipient = Keypair.generate(); - const ixArgs = { - amount: new anchor.BN(LAMPORTS_PER_SOL), - }; - const data = coder.instruction.encode("transfer_sol_with_cpi", ixArgs); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payer.publicKey, isSigner: true, isWritable: true }, - { pubkey: recipient.publicKey, isSigner: false, isWritable: true }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); + const ixArgs = { + amount: new anchor.BN(LAMPORTS_PER_SOL), + }; + const data = coder.instruction.encode("transfer_sol_with_cpi", ixArgs); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, + { pubkey: recipient.publicKey, isSigner: false, isWritable: true }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer); - svm.sendTransaction(tx); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer); + svm.sendTransaction(tx); - const recipientAcc = svm.getAccount(recipient.publicKey); - assert.equal(recipientAcc.lamports, LAMPORTS_PER_SOL); - }); + const recipientAcc = svm.getAccount(recipient.publicKey); + assert.equal(recipientAcc.lamports, LAMPORTS_PER_SOL); + }); - it("Transfer SOL with Program", () => { - const payerAccount = Keypair.generate(); - const ixPayer = SystemProgram.createAccount({ - fromPubkey: payer.publicKey, - newAccountPubkey: payerAccount.publicKey, - lamports: LAMPORTS_PER_SOL, - space: 0, - programId, - }); - const txPayer = new Transaction().add(ixPayer); - txPayer.feePayer = payer.publicKey; - txPayer.recentBlockhash = svm.latestBlockhash(); - txPayer.sign(payer, payerAccount); - svm.sendTransaction(txPayer); - svm.expireBlockhash(); + it("Transfer SOL with Program", () => { + const payerAccount = Keypair.generate(); + const ixPayer = SystemProgram.createAccount({ + fromPubkey: payer.publicKey, + newAccountPubkey: payerAccount.publicKey, + lamports: LAMPORTS_PER_SOL, + space: 0, + programId, + }); + const txPayer = new Transaction().add(ixPayer); + txPayer.feePayer = payer.publicKey; + txPayer.recentBlockhash = svm.latestBlockhash(); + txPayer.sign(payer, payerAccount); + svm.sendTransaction(txPayer); + svm.expireBlockhash(); - const recipientAccount = Keypair.generate(); + const recipientAccount = Keypair.generate(); - const ixArgs = { - amount: new anchor.BN(LAMPORTS_PER_SOL), - }; - const data = coder.instruction.encode("transfer_sol_with_program", ixArgs); - const ix = new TransactionInstruction({ - keys: [ - { pubkey: payerAccount.publicKey, isSigner: true, isWritable: true }, - { - pubkey: recipientAccount.publicKey, - isSigner: false, - isWritable: true, - }, - { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, - ], - programId, - data, - }); + const ixArgs = { + amount: new anchor.BN(LAMPORTS_PER_SOL), + }; + const data = coder.instruction.encode("transfer_sol_with_program", ixArgs); + const ix = new TransactionInstruction({ + keys: [ + { pubkey: payerAccount.publicKey, isSigner: true, isWritable: true }, + { + pubkey: recipientAccount.publicKey, + isSigner: false, + isWritable: true, + }, + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, + ], + programId, + data, + }); - const tx = new Transaction().add(ix); - tx.feePayer = payer.publicKey; - tx.recentBlockhash = svm.latestBlockhash(); - tx.sign(payer, payerAccount); - svm.sendTransaction(tx); + const tx = new Transaction().add(ix); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = svm.latestBlockhash(); + tx.sign(payer, payerAccount); + svm.sendTransaction(tx); - const recipientAcc = svm.getAccount(recipientAccount.publicKey); - assert.equal(recipientAcc.lamports, LAMPORTS_PER_SOL); - }); + const recipientAcc = svm.getAccount(recipientAccount.publicKey); + assert.equal(recipientAcc.lamports, LAMPORTS_PER_SOL); + }); }); diff --git a/basics/transfer-sol/anchor/tests/test.ts b/basics/transfer-sol/anchor/tests/test.ts index c43f5f122..3f773a536 100644 --- a/basics/transfer-sol/anchor/tests/test.ts +++ b/basics/transfer-sol/anchor/tests/test.ts @@ -1,68 +1,54 @@ import * as anchor from "@anchor-lang/core"; -import { - Keypair, - LAMPORTS_PER_SOL, - type PublicKey, - SystemProgram, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; +import { Keypair, LAMPORTS_PER_SOL, SystemProgram, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; import { BN } from "bn.js"; import { assert } from "chai"; import type { TransferSol } from "../target/types/transfer_sol.ts"; describe("Anchor: Transfer SOL", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - const program = anchor.workspace.TransferSol as anchor.Program; - - it("Transfer SOL with CPI", async () => { - const recipient = Keypair.generate(); - - await program.methods - .transferSolWithCpi(new BN(LAMPORTS_PER_SOL)) - .accounts({ - payer: payer.publicKey, - recipient: recipient.publicKey, - }) - .rpc(); - - const recipientBalance = await provider.connection.getBalance( - recipient.publicKey, - ); - assert.equal(recipientBalance, LAMPORTS_PER_SOL); - }); - - it("Transfer SOL with Program", async () => { - const payerAccount = Keypair.generate(); - const ix = SystemProgram.createAccount({ - fromPubkey: payer.publicKey, - newAccountPubkey: payerAccount.publicKey, - space: 0, - lamports: LAMPORTS_PER_SOL, // 1 SOL - programId: program.programId, // Program Owner, our program's address - }); - - const transaction = new Transaction().add(ix); - - await sendAndConfirmTransaction(provider.connection, transaction, [ - payer.payer, - payerAccount, - ]); - - const recipientAccount = Keypair.generate(); - await program.methods - .transferSolWithProgram(new BN(LAMPORTS_PER_SOL)) - .accounts({ - payer: payerAccount.publicKey, - recipient: recipientAccount.publicKey, - }) - .rpc(); - - const recipientBalance = await provider.connection.getBalance( - recipientAccount.publicKey, - ); - assert.equal(recipientBalance, LAMPORTS_PER_SOL); - }); + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const payer = provider.wallet as anchor.Wallet; + const program = anchor.workspace.TransferSol as anchor.Program; + + it("Transfer SOL with CPI", async () => { + const recipient = Keypair.generate(); + + await program.methods + .transferSolWithCpi(new BN(LAMPORTS_PER_SOL)) + .accounts({ + payer: payer.publicKey, + recipient: recipient.publicKey, + }) + .rpc(); + + const recipientBalance = await provider.connection.getBalance(recipient.publicKey); + assert.equal(recipientBalance, LAMPORTS_PER_SOL); + }); + + it("Transfer SOL with Program", async () => { + const payerAccount = Keypair.generate(); + const ix = SystemProgram.createAccount({ + fromPubkey: payer.publicKey, + newAccountPubkey: payerAccount.publicKey, + space: 0, + lamports: LAMPORTS_PER_SOL, // 1 SOL + programId: program.programId, // Program Owner, our program's address + }); + + const transaction = new Transaction().add(ix); + + await sendAndConfirmTransaction(provider.connection, transaction, [payer.payer, payerAccount]); + + const recipientAccount = Keypair.generate(); + await program.methods + .transferSolWithProgram(new BN(LAMPORTS_PER_SOL)) + .accounts({ + payer: payerAccount.publicKey, + recipient: recipientAccount.publicKey, + }) + .rpc(); + + const recipientBalance = await provider.connection.getBalance(recipientAccount.publicKey); + assert.equal(recipientBalance, LAMPORTS_PER_SOL); + }); }); diff --git a/basics/transfer-sol/anchor/tsconfig.json b/basics/transfer-sol/anchor/tsconfig.json index 59fe75cf0..beb254c00 100644 --- a/basics/transfer-sol/anchor/tsconfig.json +++ b/basics/transfer-sol/anchor/tsconfig.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], - "module": "nodenext", - "target": "es6", - "esModuleInterop": true - } + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "nodenext", + "target": "es6", + "esModuleInterop": true + } } diff --git a/basics/transfer-sol/native/program/Cargo.toml b/basics/transfer-sol/native/program/Cargo.toml index 821c85031..9202a2596 100644 --- a/basics/transfer-sol/native/program/Cargo.toml +++ b/basics/transfer-sol/native/program/Cargo.toml @@ -20,7 +20,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/transfer-sol/native/tests/instruction.ts b/basics/transfer-sol/native/tests/instruction.ts index 311a35188..72e90f9d2 100644 --- a/basics/transfer-sol/native/tests/instruction.ts +++ b/basics/transfer-sol/native/tests/instruction.ts @@ -1,6 +1,6 @@ -import { Buffer } from 'node:buffer'; -import { type PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; +import { Buffer } from "node:buffer"; +import { type PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; export enum InstructionType { CpiTransfer = 0, @@ -9,8 +9,8 @@ export enum InstructionType { const TransferInstructionSchema = { struct: { - instruction: 'u8', - amount: 'u64', + instruction: "u8", + amount: "u64", }, }; diff --git a/basics/transfer-sol/native/tests/test.ts b/basics/transfer-sol/native/tests/test.ts index e5eb81b02..929fb0a3f 100644 --- a/basics/transfer-sol/native/tests/test.ts +++ b/basics/transfer-sol/native/tests/test.ts @@ -1,11 +1,11 @@ -import { describe, test } from 'node:test'; -import { Keypair, LAMPORTS_PER_SOL, PublicKey, SystemProgram, Transaction } from '@solana/web3.js'; -import { start } from 'solana-bankrun'; -import { createTransferInstruction, InstructionType } from './instruction'; +import { describe, test } from "node:test"; +import { Keypair, LAMPORTS_PER_SOL, PublicKey, SystemProgram, Transaction } from "@solana/web3.js"; +import { start } from "solana-bankrun"; +import { createTransferInstruction, InstructionType } from "./instruction"; -describe('transfer-sol', async () => { +describe("transfer-sol", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'transfer_sol_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "transfer_sol_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; @@ -14,10 +14,16 @@ describe('transfer-sol', async () => { const test2Recipient1 = Keypair.generate(); const test2Recipient2 = Keypair.generate(); - test('Transfer between accounts using the system program', async () => { - await getBalances(payer.publicKey, test1Recipient.publicKey, 'Beginning'); + test("Transfer between accounts using the system program", async () => { + await getBalances(payer.publicKey, test1Recipient.publicKey, "Beginning"); - const ix = createTransferInstruction(payer.publicKey, test1Recipient.publicKey, PROGRAM_ID, InstructionType.CpiTransfer, transferAmount); + const ix = createTransferInstruction( + payer.publicKey, + test1Recipient.publicKey, + PROGRAM_ID, + InstructionType.CpiTransfer, + transferAmount, + ); const tx = new Transaction(); const [blockhash, _] = await client.getLatestBlockhash(); @@ -26,10 +32,10 @@ describe('transfer-sol', async () => { await client.processTransaction(tx); - await getBalances(payer.publicKey, test1Recipient.publicKey, 'Resulting'); + await getBalances(payer.publicKey, test1Recipient.publicKey, "Resulting"); }); - test('Create two accounts for the following test', async () => { + test("Create two accounts for the following test", async () => { const ix = (pubkey: PublicKey) => { return SystemProgram.createAccount({ fromPubkey: payer.publicKey, @@ -43,13 +49,15 @@ describe('transfer-sol', async () => { const tx = new Transaction(); const [blockhash, _] = await client.getLatestBlockhash(); tx.recentBlockhash = blockhash; - tx.add(ix(test2Recipient1.publicKey)).add(ix(test2Recipient2.publicKey)).sign(payer, test2Recipient1, test2Recipient2); + tx.add(ix(test2Recipient1.publicKey)) + .add(ix(test2Recipient2.publicKey)) + .sign(payer, test2Recipient1, test2Recipient2); await client.processTransaction(tx); }); - test('Transfer between accounts using our program', async () => { - await getBalances(test2Recipient1.publicKey, test2Recipient2.publicKey, 'Beginning'); + test("Transfer between accounts using our program", async () => { + await getBalances(test2Recipient1.publicKey, test2Recipient2.publicKey, "Beginning"); const ix = createTransferInstruction( test2Recipient1.publicKey, @@ -66,7 +74,7 @@ describe('transfer-sol', async () => { await client.processTransaction(tx); - await getBalances(test2Recipient1.publicKey, test2Recipient2.publicKey, 'Resulting'); + await getBalances(test2Recipient1.publicKey, test2Recipient2.publicKey, "Resulting"); }); async function getBalances(payerPubkey: PublicKey, recipientPubkey: PublicKey, timeframe: string) { diff --git a/basics/transfer-sol/pinocchio/program/Cargo.toml b/basics/transfer-sol/pinocchio/program/Cargo.toml index aec50f992..570467285 100644 --- a/basics/transfer-sol/pinocchio/program/Cargo.toml +++ b/basics/transfer-sol/pinocchio/program/Cargo.toml @@ -18,7 +18,7 @@ custom-panic = [] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } [dev-dependencies] -litesvm = "0.8.1" +litesvm = "0.11.0" solana-instruction = "3.0.0" solana-keypair = "3.0.1" solana-native-token = "3.0.0" diff --git a/basics/transfer-sol/pinocchio/tests/test.ts b/basics/transfer-sol/pinocchio/tests/test.ts index 40dda0916..561e1d988 100644 --- a/basics/transfer-sol/pinocchio/tests/test.ts +++ b/basics/transfer-sol/pinocchio/tests/test.ts @@ -1,12 +1,4 @@ -import { describe, test } from "node:test"; -import { - Keypair, - LAMPORTS_PER_SOL, - PublicKey, - SystemProgram, - Transaction, -} from "@solana/web3.js"; -import { start } from "solana-bankrun"; +import { describe } from "node:test"; describe("transfer-sol", async () => { console.log("transfer-sol"); diff --git a/biome.jsonc b/biome.jsonc new file mode 100644 index 000000000..6243cd87c --- /dev/null +++ b/biome.jsonc @@ -0,0 +1,27 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.4.10/schema.json", + "files": { + "includes": ["**", "!**/Assets"] + }, + "formatter": { + // Matches more existing code, + // also 2 spaces is used by: Prettier, StandardJS, AirBnB, + // Google JavaScript Style Guide, node.js style guide, + // deno fmt, MDN, and idiomatic.js. + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 120 + }, + "javascript": { + "formatter": { + // Also to match Prettier, Google, etc. + // (though standard and AirBnB use single) + "quoteStyle": "double" + } + }, + "css": { + "parser": { + "tailwindDirectives": true + } + } +} diff --git a/compression/cnft-burn/anchor/Anchor.toml b/compression/cnft-burn/anchor/Anchor.toml index 8917c2a49..18ebc14e8 100644 --- a/compression/cnft-burn/anchor/Anchor.toml +++ b/compression/cnft-burn/anchor/Anchor.toml @@ -5,14 +5,14 @@ solana_version = "3.1.8" resolution = true skip-lint = false -[programs.devnet] -cnft_burn = "C6qxH8n6mZxrrbtMtYWYSp8JR8vkQ55X1o4EBg7twnMv" - -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +cnft_burn = "HELUXAsLsF3wVoehtbcvQyUafUdMiFxbJG6MPiCRnzwm" [provider] -cluster = "devnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/cnft-burn.ts" + +[hooks] diff --git a/compression/cnft-burn/anchor/migrations/deploy.ts b/compression/cnft-burn/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/compression/cnft-burn/anchor/migrations/deploy.ts +++ b/compression/cnft-burn/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/compression/cnft-burn/anchor/package.json b/compression/cnft-burn/anchor/package.json index bfbe65494..125ffb7fe 100644 --- a/compression/cnft-burn/anchor/package.json +++ b/compression/cnft-burn/anchor/package.json @@ -1,27 +1,27 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@metaplex-foundation/js": "^0.19.4", - "@metaplex-foundation/mpl-bubblegum": "^0.7.0", - "@metaplex-foundation/mpl-token-metadata": "^2.12.0", - "@metaplex-foundation/umi": "^0.9.0", - "@solana/spl-account-compression": "^0.2.0", - "@solana/web3.js": "^1.98.4", - "axios": "^1.6.5" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@metaplex-foundation/js": "^0.19.4", + "@metaplex-foundation/mpl-bubblegum": "^0.7.0", + "@metaplex-foundation/mpl-token-metadata": "^2.12.0", + "@metaplex-foundation/umi": "^0.9.0", + "@solana/spl-account-compression": "^0.2.0", + "@solana/web3.js": "^1.98.4", + "axios": "^1.6.5" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/compression/cnft-burn/anchor/pnpm-lock.yaml b/compression/cnft-burn/anchor/pnpm-lock.yaml index d0ff87a05..e1b0c15c9 100644 --- a/compression/cnft-burn/anchor/pnpm-lock.yaml +++ b/compression/cnft-burn/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) '@metaplex-foundation/js': specifier: ^0.19.4 version: 0.19.5(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@6.0.6) @@ -60,18 +60,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.6': @@ -1656,16 +1656,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 @@ -1683,7 +1683,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.6': dependencies: diff --git a/compression/cnft-burn/anchor/programs/cnft-burn/Cargo.toml b/compression/cnft-burn/anchor/programs/cnft-burn/Cargo.toml index b63449767..e23472777 100644 --- a/compression/cnft-burn/anchor/programs/cnft-burn/Cargo.toml +++ b/compression/cnft-burn/anchor/programs/cnft-burn/Cargo.toml @@ -20,13 +20,11 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" # mpl-bubblegum and spl-account-compression removed: they depend on solana-program 2.x # which is incompatible with Anchor 1.0's solana 3.x types. CPI calls are built manually # using raw invoke() with hardcoded program IDs and discriminators. borsh = "1" -ahash = "=0.8.7" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/compression/cnft-burn/anchor/programs/cnft-burn/src/lib.rs b/compression/cnft-burn/anchor/programs/cnft-burn/src/lib.rs index 58d303426..305951183 100644 --- a/compression/cnft-burn/anchor/programs/cnft-burn/src/lib.rs +++ b/compression/cnft-burn/anchor/programs/cnft-burn/src/lib.rs @@ -5,7 +5,7 @@ use anchor_lang::solana_program::{ }; use borsh::BorshSerialize; -declare_id!("C6qxH8n6mZxrrbtMtYWYSp8JR8vkQ55X1o4EBg7twnMv"); +declare_id!("HELUXAsLsF3wVoehtbcvQyUafUdMiFxbJG6MPiCRnzwm"); /// mpl-bubblegum program ID (BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY) const MPL_BUBBLEGUM_ID: Pubkey = Pubkey::new_from_array([ diff --git a/compression/cnft-burn/anchor/tests/ReadApi/WrapperConnection.ts b/compression/cnft-burn/anchor/tests/ReadApi/WrapperConnection.ts index 0f20ec043..426f6ba6b 100644 --- a/compression/cnft-burn/anchor/tests/ReadApi/WrapperConnection.ts +++ b/compression/cnft-burn/anchor/tests/ReadApi/WrapperConnection.ts @@ -1,12 +1,12 @@ // local imports for the ReadApi types -import type { Metadata, Mint, NftOriginalEdition, SplTokenCurrency } from '@metaplex-foundation/js'; +import type { Metadata, Mint, NftOriginalEdition, SplTokenCurrency } from "@metaplex-foundation/js"; // import from the `@metaplex-foundation/js` -import { amount, MetaplexError, Pda, toBigNumber } from '@metaplex-foundation/js'; -import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from '@metaplex-foundation/mpl-bubblegum'; -import { TokenStandard } from '@metaplex-foundation/mpl-token-metadata'; -import { Connection, PublicKey } from '@solana/web3.js'; -import BN from 'bn.js'; +import { amount, MetaplexError, Pda, toBigNumber } from "@metaplex-foundation/js"; +import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum"; +import { TokenStandard } from "@metaplex-foundation/mpl-token-metadata"; +import { Connection, PublicKey } from "@solana/web3.js"; +import BN from "bn.js"; import type { GetAssetProofRpcInput, GetAssetProofRpcResponse, @@ -15,7 +15,7 @@ import type { GetAssetsByOwnerRpcInput, ReadApiAsset, ReadApiAssetList, -} from '@/ReadApi/types'; +} from "@/ReadApi/types"; type JsonRpcParams = { method: string; @@ -29,9 +29,9 @@ type JsonRpcOutput = { /** @group Errors */ export class ReadApiError extends MetaplexError { - readonly name: string = 'ReadApiError'; + readonly name: string = "ReadApiError"; constructor(message: string, cause?: Error) { - super(message, 'rpc', undefined, cause); + super(message, "rpc", undefined, cause); } } @@ -40,7 +40,7 @@ export class ReadApiError extends MetaplexError { */ export const toNftEditionFromReadApiAsset = (input: ReadApiAsset): NftOriginalEdition => { return { - model: 'nftEdition', + model: "nftEdition", isOriginal: true, address: new PublicKey(input.id), supply: toBigNumber(input.supply.print_current_supply), @@ -53,13 +53,13 @@ export const toNftEditionFromReadApiAsset = (input: ReadApiAsset): NftOriginalEd */ export const toMintFromReadApiAsset = (input: ReadApiAsset): Mint => { const currency: SplTokenCurrency = { - symbol: 'Token', + symbol: "Token", decimals: 0, - namespace: 'spl-token', + namespace: "spl-token", }; return { - model: 'mint', + model: "mint", address: new PublicKey(input.id), mintAuthorityAddress: new PublicKey(input.id), freezeAuthorityAddress: new PublicKey(input.id), @@ -74,26 +74,26 @@ export const toMintFromReadApiAsset = (input: ReadApiAsset): Mint => { * Convert a ReadApi asset's data into standard Metaplex `Metadata` */ export const toMetadataFromReadApiAsset = (input: ReadApiAsset): Metadata => { - const updateAuthority = input.authorities?.find((authority) => authority.scopes.includes('full')); + const updateAuthority = input.authorities?.find((authority) => authority.scopes.includes("full")); - const collection = input.grouping.find(({ group_key }) => group_key === 'collection'); + const collection = input.grouping.find(({ group_key }) => group_key === "collection"); return { - model: 'metadata', + model: "metadata", /** * We technically don't have a metadata address anymore. * So we are using the asset's id as the address */ address: Pda.find(BUBBLEGUM_PROGRAM_ID, [ - Buffer.from('asset', 'utf-8'), + Buffer.from("asset", "utf-8"), new PublicKey(input.compression.tree).toBuffer(), - Uint8Array.from(new BN(input.compression.leaf_id).toArray('le', 8)), + Uint8Array.from(new BN(input.compression.leaf_id).toArray("le", 8)), ]), mintAddress: new PublicKey(input.id), updateAuthorityAddress: new PublicKey(updateAuthority?.address), - name: input.content.metadata?.name ?? '', - symbol: input.content.metadata?.symbol ?? '', + name: input.content.metadata?.name ?? "", + symbol: input.content.metadata?.symbol ?? "", json: input.content.metadata, jsonLoaded: true, @@ -132,14 +132,14 @@ export class WrapperConnection extends Connection { jsonRpcParams: JsonRpcParams, ): Promise> => { const response = await fetch(this.rpcEndpoint, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify({ - jsonrpc: '2.0', + jsonrpc: "2.0", method: jsonRpcParams.method, - id: jsonRpcParams.id ?? 'rpd-op-123', + id: jsonRpcParams.id ?? "rpd-op-123", params: jsonRpcParams.params, }), }); @@ -151,13 +151,13 @@ export class WrapperConnection extends Connection { // It is a PDA with the following seeds: ["asset", tree, leafIndex] async getAsset(assetId: PublicKey): Promise { const { result: asset } = await this.callReadApi({ - method: 'getAsset', + method: "getAsset", params: { id: assetId.toBase58(), }, }); - if (!asset) throw new ReadApiError('No asset returned'); + if (!asset) throw new ReadApiError("No asset returned"); return asset; } @@ -166,26 +166,35 @@ export class WrapperConnection extends Connection { // It is a PDA with the following seeds: ["asset", tree, leafIndex] async getAssetProof(assetId: PublicKey): Promise { const { result: proof } = await this.callReadApi({ - method: 'getAssetProof', + method: "getAssetProof", params: { id: assetId.toBase58(), }, }); - if (!proof) throw new ReadApiError('No asset proof returned'); + if (!proof) throw new ReadApiError("No asset proof returned"); return proof; } // - async getAssetsByGroup({ groupKey, groupValue, page, limit, sortBy, before, after }: GetAssetsByGroupRpcInput): Promise { + async getAssetsByGroup({ + groupKey, + groupValue, + page, + limit, + sortBy, + before, + after, + }: GetAssetsByGroupRpcInput): Promise { // `page` cannot be supplied with `before` or `after` - if (typeof page === 'number' && (before || after)) throw new ReadApiError('Pagination Error. Only one pagination parameter supported per query.'); + if (typeof page === "number" && (before || after)) + throw new ReadApiError("Pagination Error. Only one pagination parameter supported per query."); // a pagination method MUST be selected, but we are defaulting to using `page=0` const { result } = await this.callReadApi({ - method: 'getAssetsByGroup', + method: "getAssetsByGroup", params: { groupKey, groupValue, @@ -197,20 +206,28 @@ export class WrapperConnection extends Connection { }, }); - if (!result) throw new ReadApiError('No results returned'); + if (!result) throw new ReadApiError("No results returned"); return result; } // - async getAssetsByOwner({ ownerAddress, page, limit, sortBy, before, after }: GetAssetsByOwnerRpcInput): Promise { + async getAssetsByOwner({ + ownerAddress, + page, + limit, + sortBy, + before, + after, + }: GetAssetsByOwnerRpcInput): Promise { // `page` cannot be supplied with `before` or `after` - if (typeof page === 'number' && (before || after)) throw new ReadApiError('Pagination Error. Only one pagination parameter supported per query.'); + if (typeof page === "number" && (before || after)) + throw new ReadApiError("Pagination Error. Only one pagination parameter supported per query."); // a pagination method MUST be selected, but we are defaulting to using `page=0` const { result } = await this.callReadApi({ - method: 'getAssetsByOwner', + method: "getAssetsByOwner", params: { ownerAddress, after: after ?? null, @@ -221,7 +238,7 @@ export class WrapperConnection extends Connection { }, }); - if (!result) throw new ReadApiError('No results returned'); + if (!result) throw new ReadApiError("No results returned"); return result; } diff --git a/compression/cnft-burn/anchor/tests/ReadApi/types.ts b/compression/cnft-burn/anchor/tests/ReadApi/types.ts index a49e40fb0..b5c14b296 100644 --- a/compression/cnft-burn/anchor/tests/ReadApi/types.ts +++ b/compression/cnft-burn/anchor/tests/ReadApi/types.ts @@ -2,25 +2,25 @@ Types specific to the ReadApi */ -import type { Metadata, Option } from '@metaplex-foundation/js'; -import type { ConcurrentMerkleTreeAccount } from '@solana/spl-account-compression'; +import type { Metadata, Option } from "@metaplex-foundation/js"; +import type { ConcurrentMerkleTreeAccount } from "@solana/spl-account-compression"; export type ReadApiAssetInterface = - | 'V1_NFT' - | 'V1_PRINT' - | 'LEGACY_NFT' - | 'V2_NFT' - | 'FungibleAsset' - | 'Custom' - | 'Identity' - | 'Executable' - | 'ProgrammableNFT'; + | "V1_NFT" + | "V1_PRINT" + | "LEGACY_NFT" + | "V2_NFT" + | "FungibleAsset" + | "Custom" + | "Identity" + | "Executable" + | "ProgrammableNFT"; -export type ReadApiPropGroupKey = 'collection'; +export type ReadApiPropGroupKey = "collection"; -export type ReadApiPropSortBy = 'created' | 'updated' | 'recent_action'; +export type ReadApiPropSortBy = "created" | "updated" | "recent_action"; -export type ReadApiPropSortDirection = 'asc' | 'desc'; +export type ReadApiPropSortDirection = "asc" | "desc"; export type TransferNftCompressionParam = { ownership?: ReadApiOwnershipMetadata; @@ -36,7 +36,7 @@ export type ReadApiParamAssetSortBy = { export type ReadApiAssetContent = { json_uri: string; - metadata: Metadata['json']; + metadata: Metadata["json"]; }; export type ReadApiCompressionMetadata = { @@ -55,7 +55,7 @@ export type ReadApiOwnershipMetadata = { delegated: boolean; delegate: string | null; owner: string; - ownership_model: 'single' | 'token'; + ownership_model: "single" | "token"; }; export type ReadApiAssetSupplyMetadata = { @@ -74,7 +74,7 @@ export type ReadApiAssetGrouping = { group_value: string; }; -export type ReadApiAuthorityScope = 'full'; +export type ReadApiAuthorityScope = "full"; export type ReadApiAssetAuthority = { address: string; @@ -133,7 +133,7 @@ export type ReadApiAsset = { content: ReadApiAssetContent; royalty: ReadApiAssetRoyaltyMetadata; supply: ReadApiAssetSupplyMetadata; - creators: Metadata['creators']; + creators: Metadata["creators"]; grouping: Array; compression: ReadApiCompressionMetadata; }; diff --git a/compression/cnft-burn/anchor/tests/cnft-burn.ts b/compression/cnft-burn/anchor/tests/cnft-burn.ts index c2e9464ef..5bc3047c9 100644 --- a/compression/cnft-burn/anchor/tests/cnft-burn.ts +++ b/compression/cnft-burn/anchor/tests/cnft-burn.ts @@ -1,17 +1,17 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from '@metaplex-foundation/mpl-bubblegum'; -import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from '@solana/spl-account-compression'; -import type { CnftBurn } from '../target/types/cnft_burn'; -import { createAndMint } from './createAndMint'; -import { getcNFTsFromCollection } from './fetchNFTsByCollection'; -import { getAsset, getAssetProof } from './readApi'; -import { decode, mapProof } from './utils'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum"; +import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from "@solana/spl-account-compression"; +import type { CnftBurn } from "../target/types/cnft_burn"; +import { createAndMint } from "./createAndMint"; +import { getcNFTsFromCollection } from "./fetchNFTsByCollection"; +import { getAsset, getAssetProof } from "./readApi"; +import { decode, mapProof } from "./utils"; // Replace this with your custom RPC endpoint that supports cNFT indexing -const _RPC_PATH = 'https://api.devnet.solana.com'; +const _RPC_PATH = "https://api.devnet.solana.com"; -describe('cnft-burn', () => { +describe("cnft-burn", () => { // Configure the client to use the local cluster. anchor.setProvider(anchor.AnchorProvider.env()); @@ -23,20 +23,20 @@ describe('cnft-burn', () => { const MPL_BUBBLEGUM_PROGRAM_ID_KEY = new anchor.web3.PublicKey(BUBBLEGUM_PROGRAM_ID); // this is the assetId of the cNft you want to burn - let assetId = ''; + let assetId = ""; - it('Should create the tree and mint a cnft', async () => { + it("Should create the tree and mint a cnft", async () => { const { tree, collection } = await createAndMint(); if (!tree.treeAddress) { - throw new Error('Tree address not found'); + throw new Error("Tree address not found"); } treeAddress = tree.treeAddress; const fetchcNFTs = await getcNFTsFromCollection(collection.mint, payerWallet.publicKey.toString()); - console.log('fetchcNFTs', fetchcNFTs); + console.log("fetchcNFTs", fetchcNFTs); assetId = fetchcNFTs[0]; }); - it('Burn cNft!', async () => { + it("Burn cNft!", async () => { const asset = await getAsset(assetId); const proof = await getAssetProof(assetId); @@ -46,7 +46,10 @@ describe('cnft-burn', () => { const creatorHash = decode(asset.compression.creator_hash); const nonce = new anchor.BN(asset.compression.leaf_id); const index = asset.compression.leaf_id; - const [treeAuthority, _bump2] = anchor.web3.PublicKey.findProgramAddressSync([treeAddress.toBuffer()], MPL_BUBBLEGUM_PROGRAM_ID_KEY); + const [treeAuthority, _bump2] = anchor.web3.PublicKey.findProgramAddressSync( + [treeAddress.toBuffer()], + MPL_BUBBLEGUM_PROGRAM_ID_KEY, + ); const tx = await program.methods .burnCnft(root, dataHash, creatorHash, nonce, index) .accounts({ @@ -62,7 +65,7 @@ describe('cnft-burn', () => { .rpc({ skipPreflight: true, }); - console.log('Your transaction signature', tx); + console.log("Your transaction signature", tx); // here is a sample transaction signature on devnet // https://explorer.solana.com/tx/2MpeHi64pbWNY7BKBuhAp4yND5HdfQqNqkd8pu6F6meoSNUYRvxQgV5TC4w8BM8hUihB8G8TwBAaPRqS7pnN8Nu1?cluster=devnet }); diff --git a/compression/cnft-burn/anchor/tests/createAndMint.ts b/compression/cnft-burn/anchor/tests/createAndMint.ts index add25d3cd..7ef574b1d 100644 --- a/compression/cnft-burn/anchor/tests/createAndMint.ts +++ b/compression/cnft-burn/anchor/tests/createAndMint.ts @@ -12,18 +12,18 @@ less console logging and explanation of what is occurring */ -import * as anchor from '@anchor-lang/core'; -import { type MetadataArgs, TokenProgramVersion, TokenStandard } from '@metaplex-foundation/mpl-bubblegum'; -import type { CreateMetadataAccountArgsV3 } from '@metaplex-foundation/mpl-token-metadata'; -import type { ValidDepthSizePair } from '@solana/spl-account-compression'; -import { Keypair, LAMPORTS_PER_SOL } from '@solana/web3.js'; -import { RPC_PATH } from './cnft-burn'; +import * as anchor from "@anchor-lang/core"; +import { type MetadataArgs, TokenProgramVersion, TokenStandard } from "@metaplex-foundation/mpl-bubblegum"; +import type { CreateMetadataAccountArgsV3 } from "@metaplex-foundation/mpl-token-metadata"; +import type { ValidDepthSizePair } from "@solana/spl-account-compression"; +import { Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js"; +import { RPC_PATH } from "./cnft-burn"; // local import of the connection wrapper, to help with using the ReadApi -import { WrapperConnection } from './ReadApi/WrapperConnection'; +import { WrapperConnection } from "./ReadApi/WrapperConnection"; // import custom helpers to mint compressed NFTs -import { createCollection, createTree, mintCompressedNFT } from './utils/compression'; +import { createCollection, createTree, mintCompressedNFT } from "./utils/compression"; // import custom helpers for demos -import { numberFormatter } from './utils/helpers'; +import { numberFormatter } from "./utils/helpers"; // define some reusable balance values for tracking let initBalance: number; @@ -39,7 +39,7 @@ export async function createAndMint() { const payerWallet = provider.wallet as anchor.Wallet; const payer = payerWallet.payer; - console.log('Payer address:', payer.publicKey.toBase58()); + console.log("Payer address:", payer.publicKey.toBase58()); ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -48,7 +48,7 @@ export async function createAndMint() { const CLUSTER_URL = RPC_PATH; // create a new rpc connection, using the ReadApi wrapper - const connection = new WrapperConnection(CLUSTER_URL, 'confirmed'); + const connection = new WrapperConnection(CLUSTER_URL, "confirmed"); // get the payer's starting balance (only used for demonstration purposes) initBalance = await connection.getBalance(payer.publicKey); @@ -84,10 +84,10 @@ export async function createAndMint() { // define the metadata to be used for creating the NFT collection const collectionMetadataV3: CreateMetadataAccountArgsV3 = { data: { - name: 'Test Burn', - symbol: 'TB', + name: "Test Burn", + symbol: "TB", // specific json metadata for the collection - uri: 'https://supersweetcollection.notarealurl/collection.json', + uri: "https://supersweetcollection.notarealurl/collection.json", sellerFeeBasisPoints: 100, creators: [ { @@ -111,10 +111,10 @@ export async function createAndMint() { */ const compressedNFTMetadata: MetadataArgs = { - name: 'Pratik test', + name: "Pratik test", symbol: collectionMetadataV3.data.symbol, // specific json metadata for each NFT - uri: 'https://bafkreies5r7b5eszpq5dgnw2brhjtlw7xtdtmsmoniebqehf37nv5rxajy.ipfs.nftstorage.link/', + uri: "https://bafkreies5r7b5eszpq5dgnw2brhjtlw7xtdtmsmoniebqehf37nv5rxajy.ipfs.nftstorage.link/", creators: [ { address: payer.publicKey, @@ -154,8 +154,8 @@ export async function createAndMint() { // fetch the payer's final balance balance = await connection.getBalance(payer.publicKey); - console.log('==============================='); - console.log('Total cost:', numberFormatter((initBalance - balance) / LAMPORTS_PER_SOL, true), 'SOL\n'); + console.log("==============================="); + console.log("Total cost:", numberFormatter((initBalance - balance) / LAMPORTS_PER_SOL, true), "SOL\n"); return { tree, collection }; } diff --git a/compression/cnft-burn/anchor/tests/fetchNFTsByCollection.ts b/compression/cnft-burn/anchor/tests/fetchNFTsByCollection.ts index e12114ee5..11fef4d0a 100644 --- a/compression/cnft-burn/anchor/tests/fetchNFTsByCollection.ts +++ b/compression/cnft-burn/anchor/tests/fetchNFTsByCollection.ts @@ -4,13 +4,13 @@ */ // imports from other libraries -import type { PublicKey } from '@solana/web3.js'; -import { RPC_PATH } from './cnft-burn'; +import type { PublicKey } from "@solana/web3.js"; +import { RPC_PATH } from "./cnft-burn"; // local import of the connection wrapper, to help with using the ReadApi -import { WrapperConnection } from './ReadApi/WrapperConnection'; +import { WrapperConnection } from "./ReadApi/WrapperConnection"; // import custom helpers for demos -import { printConsoleSeparator } from './utils/helpers'; +import { printConsoleSeparator } from "./utils/helpers"; export async function getcNFTsFromCollection(collectionMint: PublicKey, owner: string) { // load the stored PublicKeys for ease of use @@ -23,7 +23,7 @@ export async function getcNFTsFromCollection(collectionMint: PublicKey, owner: s // convert the locally saved keys to PublicKeys // const collectionMint: PublicKey = keys.collectionMint; - console.log('Collection mint:', collectionMint.toBase58()); + console.log("Collection mint:", collectionMint.toBase58()); ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -38,31 +38,31 @@ export async function getcNFTsFromCollection(collectionMint: PublicKey, owner: s const assets = await connection .getAssetsByGroup({ - groupKey: 'collection', + groupKey: "collection", groupValue: collectionMint.toBase58(), sortBy: { - sortBy: 'recent_action', - sortDirection: 'asc', + sortBy: "recent_action", + sortDirection: "asc", }, }) .then((res) => { - console.log('Total assets returned:', res.total); + console.log("Total assets returned:", res.total); // loop over each of the asset items in the collection const assetsIds = res.items?.map((asset) => { // display a spacer between each of the assets - console.log('\n==============================================='); + console.log("\n==============================================="); // print the entire asset record to the console // console.log(asset); // print some useful info - console.log('assetId:', asset.id); - console.log('ownership:', asset.ownership); - console.log('compression:', asset.compression); + console.log("assetId:", asset.id); + console.log("ownership:", asset.ownership); + console.log("compression:", asset.compression); if (asset.ownership?.owner === owner) { - console.log('assetId:', asset.id); + console.log("assetId:", asset.id); return asset.id; } return undefined; diff --git a/compression/cnft-burn/anchor/tests/readApi.ts b/compression/cnft-burn/anchor/tests/readApi.ts index 0ee382850..87b9c4e0e 100644 --- a/compression/cnft-burn/anchor/tests/readApi.ts +++ b/compression/cnft-burn/anchor/tests/readApi.ts @@ -2,20 +2,21 @@ // as it supports more readAPI functionality // this is just a subset of functions for quick availabiity -import axios from 'axios'; -import { RPC_PATH } from './cnft-burn'; +import axios from "axios"; +import { RPC_PATH } from "./cnft-burn"; // you might want to change that to your custom RPC endpoint as this endpoint is not going to work as it does not support DAS +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 export async function getAsset(assetId: any, rpcUrl = RPC_PATH): Promise { try { const axiosInstance = axios.create({ baseURL: rpcUrl, }); const response = await axiosInstance.post(rpcUrl, { - jsonrpc: '2.0', - method: 'getAsset', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAsset", + id: "rpd-op-123", params: { id: assetId, }, @@ -26,15 +27,16 @@ export async function getAsset(assetId: any, rpcUrl = RPC_PATH): Promise { } } +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 export async function getAssetProof(assetId: any, rpcUrl = RPC_PATH): Promise { try { const axiosInstance = axios.create({ baseURL: rpcUrl, }); const response = await axiosInstance.post(rpcUrl, { - jsonrpc: '2.0', - method: 'getAssetProof', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAssetProof", + id: "rpd-op-123", params: { id: assetId, }, diff --git a/compression/cnft-burn/anchor/tests/utils.ts b/compression/cnft-burn/anchor/tests/utils.ts index 43759dd36..70aa141d9 100644 --- a/compression/cnft-burn/anchor/tests/utils.ts +++ b/compression/cnft-burn/anchor/tests/utils.ts @@ -1,9 +1,9 @@ -import { type AccountMeta, Keypair, PublicKey } from '@solana/web3.js'; +import { type AccountMeta, Keypair, PublicKey } from "@solana/web3.js"; -import * as bs58 from 'bs58'; +import * as bs58 from "bs58"; export function loadWalletKey(keypairFile: string): Keypair { - const fs = require('node:fs'); + const fs = require("node:fs"); return Keypair.fromSecretKey(new Uint8Array(JSON.parse(fs.readFileSync(keypairFile).toString()))); } @@ -19,7 +19,7 @@ function bufferToArray(buffer: Buffer): number[] { } export const mapProof = (assetProof: { proof: string[] }): AccountMeta[] => { if (!assetProof.proof || assetProof.proof.length === 0) { - throw new Error('Proof is empty'); + throw new Error("Proof is empty"); } return assetProof.proof.map((node) => ({ pubkey: new PublicKey(node), diff --git a/compression/cnft-burn/anchor/tests/utils/compression.ts b/compression/cnft-burn/anchor/tests/utils/compression.ts index 3e3e7d01a..b91ee1170 100644 --- a/compression/cnft-burn/anchor/tests/utils/compression.ts +++ b/compression/cnft-burn/anchor/tests/utils/compression.ts @@ -5,20 +5,32 @@ import { createCreateTreeInstruction, createMintToCollectionV1Instruction, type MetadataArgs, -} from '@metaplex-foundation/mpl-bubblegum'; +} from "@metaplex-foundation/mpl-bubblegum"; import { type CreateMetadataAccountArgsV3, createCreateMasterEditionV3Instruction, createCreateMetadataAccountV3Instruction, createSetCollectionSizeInstruction, PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID, -} from '@metaplex-foundation/mpl-token-metadata'; -import { createAllocTreeIx, SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID, type ValidDepthSizePair } from '@solana/spl-account-compression'; -import { createAccount, createMint, mintTo, TOKEN_PROGRAM_ID } from '@solana/spl-token'; -import { type Connection, type Keypair, PublicKey, sendAndConfirmTransaction, Transaction, type TransactionInstruction } from '@solana/web3.js'; +} from "@metaplex-foundation/mpl-token-metadata"; +import { + createAllocTreeIx, + SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, + SPL_NOOP_PROGRAM_ID, + type ValidDepthSizePair, +} from "@solana/spl-account-compression"; +import { createAccount, createMint, mintTo, TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { + type Connection, + type Keypair, + PublicKey, + sendAndConfirmTransaction, + Transaction, + type TransactionInstruction, +} from "@solana/web3.js"; // import local helper functions -import { explorerURL, extractSignatureFromFailedTransaction } from './helpers'; +import { explorerURL, extractSignatureFromFailedTransaction } from "./helpers"; /* Helper function to create a merkle tree on chain, including allocating @@ -31,16 +43,25 @@ export async function createTree( maxDepthSizePair: ValidDepthSizePair, canopyDepth = 0, ) { - console.log('Creating a new Merkle tree...'); - console.log('treeAddress:', treeKeypair.publicKey.toBase58()); + console.log("Creating a new Merkle tree..."); + console.log("treeAddress:", treeKeypair.publicKey.toBase58()); // derive the tree's authority (PDA), owned by Bubblegum - const [treeAuthority, _bump] = PublicKey.findProgramAddressSync([treeKeypair.publicKey.toBuffer()], BUBBLEGUM_PROGRAM_ID); - console.log('treeAuthority:', treeAuthority.toBase58()); + const [treeAuthority, _bump] = PublicKey.findProgramAddressSync( + [treeKeypair.publicKey.toBuffer()], + BUBBLEGUM_PROGRAM_ID, + ); + console.log("treeAuthority:", treeAuthority.toBase58()); // allocate the tree's account on chain with the `space` // NOTE: this will compute the space needed to store the tree on chain (and the lamports required to store it) - const allocTreeIx = await createAllocTreeIx(connection, treeKeypair.publicKey, payer.publicKey, maxDepthSizePair, canopyDepth); + const allocTreeIx = await createAllocTreeIx( + connection, + treeKeypair.publicKey, + payer.publicKey, + maxDepthSizePair, + canopyDepth, + ); // create the instruction to actually create the tree const createTreeIx = createCreateTreeInstruction( @@ -73,18 +94,19 @@ export async function createTree( // ensuring the `treeKeypair` PDA and the `payer` are BOTH signers [treeKeypair, payer], { - commitment: 'confirmed', + commitment: "confirmed", skipPreflight: true, }, ); - console.log('\nMerkle tree created successfully!'); + console.log("\nMerkle tree created successfully!"); console.log(explorerURL({ txSignature })); // return useful info return { treeAuthority, treeAddress: treeKeypair.publicKey }; + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 } catch (err: any) { - console.error('\nFailed to create merkle tree:', err); + console.error("\nFailed to create merkle tree:", err); // log a block explorer link for the failed transaction await extractSignatureFromFailedTransaction(connection, err); @@ -97,7 +119,11 @@ export async function createTree( * Create an NFT collection on-chain, using the regular Metaplex standards * with the `payer` as the authority */ -export async function createCollection(connection: Connection, payer: Keypair, metadataV3: CreateMetadataAccountArgsV3) { +export async function createCollection( + connection: Connection, + payer: Keypair, + metadataV3: CreateMetadataAccountArgsV3, +) { // create and initialize the SPL token mint console.log("Creating the collection's mint..."); const mint = await createMint( @@ -110,10 +136,10 @@ export async function createCollection(connection: Connection, payer: Keypair, m // decimals - use `0` for NFTs since they are non-fungible 0, ); - console.log('Mint address:', mint.toBase58()); + console.log("Mint address:", mint.toBase58()); // create the token account - console.log('Creating a token account...'); + console.log("Creating a token account..."); const tokenAccount = await createAccount( connection, payer, @@ -121,10 +147,10 @@ export async function createCollection(connection: Connection, payer: Keypair, m payer.publicKey, // undefined, undefined, ); - console.log('Token account:', tokenAccount.toBase58()); + console.log("Token account:", tokenAccount.toBase58()); // mint 1 token () - console.log('Minting 1 token for the collection...'); + console.log("Minting 1 token for the collection..."); const _mintSig = await mintTo( connection, payer, @@ -142,10 +168,10 @@ export async function createCollection(connection: Connection, payer: Keypair, m // derive the PDA for the metadata account const [metadataAccount, _bump] = PublicKey.findProgramAddressSync( - [Buffer.from('metadata', 'utf8'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], + [Buffer.from("metadata", "utf8"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], TOKEN_METADATA_PROGRAM_ID, ); - console.log('Metadata account:', metadataAccount.toBase58()); + console.log("Metadata account:", metadataAccount.toBase58()); // create an instruction to create the metadata account const createMetadataIx = createCreateMetadataAccountV3Instruction( @@ -163,10 +189,15 @@ export async function createCollection(connection: Connection, payer: Keypair, m // derive the PDA for the metadata account const [masterEditionAccount, _bump2] = PublicKey.findProgramAddressSync( - [Buffer.from('metadata', 'utf8'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer(), Buffer.from('edition', 'utf8')], + [ + Buffer.from("metadata", "utf8"), + TOKEN_METADATA_PROGRAM_ID.toBuffer(), + mint.toBuffer(), + Buffer.from("edition", "utf8"), + ], TOKEN_METADATA_PROGRAM_ID, ); - console.log('Master edition account:', masterEditionAccount.toBase58()); + console.log("Master edition account:", masterEditionAccount.toBase58()); // create an instruction to create the metadata account const createMasterEditionIx = createCreateMasterEditionV3Instruction( @@ -204,14 +235,14 @@ export async function createCollection(connection: Connection, payer: Keypair, m // send the transaction to the cluster const txSignature = await sendAndConfirmTransaction(connection, tx, [payer], { - commitment: 'confirmed', + commitment: "confirmed", skipPreflight: true, }); - console.log('\nCollection successfully created!'); + console.log("\nCollection successfully created!"); console.log(explorerURL({ txSignature })); } catch (err) { - console.error('\nFailed to create collection:', err); + console.error("\nFailed to create collection:", err); // log a block explorer link for the failed transaction await extractSignatureFromFailedTransaction(connection, err); @@ -242,7 +273,7 @@ export async function mintCompressedNFT( // derive a PDA (owned by Bubblegum) to act as the signer of the compressed minting const [bubblegumSigner, _bump2] = PublicKey.findProgramAddressSync( // `collection_cpi` is a custom prefix required by the Bubblegum program - [Buffer.from('collection_cpi', 'utf8')], + [Buffer.from("collection_cpi", "utf8")], BUBBLEGUM_PROGRAM_ID, ); @@ -269,8 +300,8 @@ export async function mintCompressedNFT( */ const computedDataHash = new PublicKey(computeDataHash(metadataArgs)).toBase58(); const computedCreatorHash = new PublicKey(computeCreatorHash(metadataArgs.creators)).toBase58(); - console.log('computedDataHash:', computedDataHash); - console.log('computedCreatorHash:', computedCreatorHash); + console.log("computedDataHash:", computedDataHash); + console.log("computedCreatorHash:", computedCreatorHash); /* Add a single mint to collection instruction @@ -326,16 +357,16 @@ export async function mintCompressedNFT( // send the transaction to the cluster const txSignature = await sendAndConfirmTransaction(connection, tx, [payer], { - commitment: 'confirmed', + commitment: "confirmed", skipPreflight: true, }); - console.log('\nSuccessfully minted the compressed NFT!'); + console.log("\nSuccessfully minted the compressed NFT!"); console.log(explorerURL({ txSignature })); return txSignature; } catch (err) { - console.error('\nFailed to mint compressed NFT:', err); + console.error("\nFailed to mint compressed NFT:", err); // log a block explorer link for the failed transaction await extractSignatureFromFailedTransaction(connection, err); diff --git a/compression/cnft-burn/anchor/tests/utils/helpers.ts b/compression/cnft-burn/anchor/tests/utils/helpers.ts index da6481353..14dcf3db8 100644 --- a/compression/cnft-burn/anchor/tests/utils/helpers.ts +++ b/compression/cnft-burn/anchor/tests/utils/helpers.ts @@ -1,11 +1,11 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import { type Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js'; +import fs from "node:fs"; +import path from "node:path"; +import { type Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js"; // define some default locations -const DEFAULT_KEY_DIR_NAME = '.local_keys'; -const DEFAULT_PUBLIC_KEY_FILE = 'keys.json'; -const DEFAULT_DEMO_DATA_FILE = 'demo.json'; +const DEFAULT_KEY_DIR_NAME = ".local_keys"; +const DEFAULT_PUBLIC_KEY_FILE = "keys.json"; +const DEFAULT_DEMO_DATA_FILE = "demo.json"; /* Load locally stored PublicKey addresses @@ -13,20 +13,20 @@ const DEFAULT_DEMO_DATA_FILE = 'demo.json'; */ export function loadPublicKeysFromFile(absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_PUBLIC_KEY_FILE}`) { try { - if (!absPath) throw Error('No path provided'); - if (!fs.existsSync(absPath)) throw Error('File does not exist.'); + if (!absPath) throw Error("No path provided"); + if (!fs.existsSync(absPath)) throw Error("File does not exist."); // load the public keys from the file - const data = JSON.parse(fs.readFileSync(absPath, { encoding: 'utf-8' })) || {}; + const data = JSON.parse(fs.readFileSync(absPath, { encoding: "utf-8" })) || {}; // convert all loaded keyed values into valid public keys for (const [key, value] of Object.entries(data)) { - data[key] = new PublicKey(value as string) ?? ''; + data[key] = new PublicKey(value as string) ?? ""; } return data; } catch (_err) { - console.warn('Unable to load local file'); + console.warn("Unable to load local file"); } // always return an object return {}; @@ -35,23 +35,28 @@ export function loadPublicKeysFromFile(absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFA /* Locally save a demo data to the filesystem for later retrieval */ -export function saveDemoDataToFile(name: string, newData: any, absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_DEMO_DATA_FILE}`) { +export function saveDemoDataToFile( + name: string, + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 + newData: any, + absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_DEMO_DATA_FILE}`, +) { try { let data: object = {}; // fetch all the current values, when the storage file exists - if (fs.existsSync(absPath)) data = JSON.parse(fs.readFileSync(absPath, { encoding: 'utf-8' })) || {}; + if (fs.existsSync(absPath)) data = JSON.parse(fs.readFileSync(absPath, { encoding: "utf-8" })) || {}; data = { ...data, [name]: newData }; // actually save the data to the file fs.writeFileSync(absPath, JSON.stringify(data), { - encoding: 'utf-8', + encoding: "utf-8", }); return data; } catch (err) { - console.warn('Unable to save to file'); + console.warn("Unable to save to file"); console.warn(err); } @@ -62,23 +67,29 @@ export function saveDemoDataToFile(name: string, newData: any, absPath = `${DEFA /* Locally save a PublicKey addresses to the filesystem for later retrieval */ -export function savePublicKeyToFile(name: string, publicKey: PublicKey, absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_PUBLIC_KEY_FILE}`) { +export function savePublicKeyToFile( + name: string, + publicKey: PublicKey, + absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_PUBLIC_KEY_FILE}`, +) { try { // if (!absPath) throw Error("No path provided"); // if (!fs.existsSync(absPath)) throw Error("File does not exist."); // fetch all the current values + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 let data: any = loadPublicKeysFromFile(absPath); // convert all loaded keyed values from PublicKeys to strings for (const [key, value] of Object.entries(data)) { + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 data[key as any] = (value as PublicKey).toBase58(); } data = { ...data, [name]: publicKey.toBase58() }; // actually save the data to the file fs.writeFileSync(absPath, JSON.stringify(data), { - encoding: 'utf-8', + encoding: "utf-8", }); // reload the keys for sanity @@ -86,7 +97,7 @@ export function savePublicKeyToFile(name: string, publicKey: PublicKey, absPath return data; } catch (_err) { - console.warn('Unable to save to file'); + console.warn("Unable to save to file"); } // always return an object return {}; @@ -97,16 +108,16 @@ export function savePublicKeyToFile(name: string, publicKey: PublicKey, absPath */ export function loadKeypairFromFile(absPath: string) { try { - if (!absPath) throw Error('No path provided'); - if (!fs.existsSync(absPath)) throw Error('File does not exist.'); + if (!absPath) throw Error("No path provided"); + if (!fs.existsSync(absPath)) throw Error("File does not exist."); // load the keypair from the file - const keyfileBytes = JSON.parse(fs.readFileSync(absPath, { encoding: 'utf-8' })); + const keyfileBytes = JSON.parse(fs.readFileSync(absPath, { encoding: "utf-8" })); // parse the loaded secretKey into a valid keypair const keypair = Keypair.fromSecretKey(new Uint8Array(keyfileBytes)); return keypair; } catch (err) { - console.error('loadKeypairFromFile:', err); + console.error("loadKeypairFromFile:", err); throw err; } } @@ -126,7 +137,7 @@ export function saveKeypairToFile(keypair: Keypair, relativeFileName: string, di // write the `secretKey` value as a string fs.writeFileSync(fileName, `[${keypair.secretKey.toString()}]`, { - encoding: 'utf-8', + encoding: "utf-8", }); return fileName; @@ -148,7 +159,7 @@ export function loadOrGenerateKeypair(fileName: string, dirName: string = DEFAUL return keypair; } catch (err) { - console.error('loadOrGenerateKeypair:', err); + console.error("loadOrGenerateKeypair:", err); throw err; } } @@ -163,17 +174,17 @@ export function explorerURL({ }: { address?: string; txSignature?: string; - cluster?: 'devnet' | 'testnet' | 'mainnet' | 'mainnet-beta'; + cluster?: "devnet" | "testnet" | "mainnet" | "mainnet-beta"; }) { let baseUrl: string; // if (address) baseUrl = `https://explorer.solana.com/address/${address}`; else if (txSignature) baseUrl = `https://explorer.solana.com/tx/${txSignature}`; - else return '[unknown]'; + else return "[unknown]"; // auto append the desired search params const url = new URL(baseUrl); - url.searchParams.append('cluster', cluster || 'devnet'); + url.searchParams.append("cluster", cluster || "devnet"); return `${url.toString()}\n`; } @@ -191,7 +202,7 @@ export async function airdropOnLowBalance(connection: Connection, keypair: Keypa if (forceAirdrop === true || balance < MIN_BALANCE_TO_AIRDROP) { console.log(`Requesting airdrop of 1 SOL to ${keypair.publicKey.toBase58()}...`); await connection.requestAirdrop(keypair.publicKey, LAMPORTS_PER_SOL).then((sig) => { - console.log('Tx signature:', sig); + console.log("Tx signature:", sig); // balance = balance + LAMPORTS_PER_SOL; }); @@ -207,11 +218,14 @@ export async function airdropOnLowBalance(connection: Connection, keypair: Keypa /* Helper function to extract a transaction signature from a failed transaction's error message */ +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 export async function extractSignatureFromFailedTransaction(connection: Connection, err: any, fetchLogs?: boolean) { if (err?.signature) return err.signature; // extract the failed transaction's signature - const failedSig = new RegExp(/^((.*)?Error: )?(Transaction|Signature) ([A-Z0-9]{32,}) /gim).exec(err?.message?.toString())?.[4]; + const failedSig = new RegExp(/^((.*)?Error: )?(Transaction|Signature) ([A-Z0-9]{32,}) /gim).exec( + err?.message?.toString(), + )?.[4]; // ensure a signature was found if (failedSig) { @@ -223,14 +237,14 @@ export async function extractSignatureFromFailedTransaction(connection: Connecti }) .then((tx) => { console.log(`\n==== Transaction logs for ${failedSig} ====`); - console.log(explorerURL({ txSignature: failedSig }), ''); - console.log(tx?.meta?.logMessages ?? 'No log messages provided by RPC'); - console.log('==== END LOGS ====\n'); + console.log(explorerURL({ txSignature: failedSig }), ""); + console.log(tx?.meta?.logMessages ?? "No log messages provided by RPC"); + console.log("==== END LOGS ====\n"); }); else { - console.log('\n========================================'); + console.log("\n========================================"); console.log(explorerURL({ txSignature: failedSig })); - console.log('========================================\n'); + console.log("========================================\n"); } } @@ -255,7 +269,7 @@ export function numberFormatter(num: number, forceDecimals = false) { Display a separator in the console, with our without a message */ export function printConsoleSeparator(message?: string) { - console.log('\n==============================================='); - console.log('===============================================\n'); + console.log("\n==============================================="); + console.log("===============================================\n"); if (message) console.log(message); } diff --git a/compression/cnft-vault/anchor/Anchor.toml b/compression/cnft-vault/anchor/Anchor.toml index b3f3533c9..3b4bc9757 100644 --- a/compression/cnft-vault/anchor/Anchor.toml +++ b/compression/cnft-vault/anchor/Anchor.toml @@ -5,13 +5,13 @@ solana_version = "3.1.8" resolution = true skip-lint = false -[programs.devnet] +[programs.localnet] cnft_vault = "Fd4iwpPWaCU8BNwGQGtvvrcvG4Tfizq3RgLm8YLBJX6D" # [registry] section removed — no longer used in Anchor 1.0 [provider] -cluster = "devnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] diff --git a/compression/cnft-vault/anchor/package.json b/compression/cnft-vault/anchor/package.json index 4aeee309a..44d4c3f72 100644 --- a/compression/cnft-vault/anchor/package.json +++ b/compression/cnft-vault/anchor/package.json @@ -1,23 +1,23 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@metaplex-foundation/mpl-bubblegum": "^0.6.2", - "@solana/spl-account-compression": "^0.1.8", - "axios": "^1.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@metaplex-foundation/mpl-bubblegum": "^0.6.2", + "@solana/spl-account-compression": "^0.1.8", + "axios": "^1.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/compression/cnft-vault/anchor/pnpm-lock.yaml b/compression/cnft-vault/anchor/pnpm-lock.yaml index c9a18387c..300c303c5 100644 --- a/compression/cnft-vault/anchor/pnpm-lock.yaml +++ b/compression/cnft-vault/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@metaplex-foundation/mpl-bubblegum': specifier: ^0.6.2 version: 0.6.2(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -48,18 +48,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.6': @@ -1064,16 +1064,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -1091,7 +1091,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.6': dependencies: diff --git a/compression/cnft-vault/anchor/programs/cnft-vault/Cargo.toml b/compression/cnft-vault/anchor/programs/cnft-vault/Cargo.toml index 1cea9f3d6..c6eee7ea3 100644 --- a/compression/cnft-vault/anchor/programs/cnft-vault/Cargo.toml +++ b/compression/cnft-vault/anchor/programs/cnft-vault/Cargo.toml @@ -20,13 +20,11 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" # mpl-bubblegum and spl-account-compression removed: they depend on solana-program 2.x # which is incompatible with Anchor 1.0's solana 3.x types. CPI calls are built manually # using raw invoke_signed() with hardcoded program IDs and discriminators. borsh = "1" -ahash = "=0.8.7" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/compression/cnft-vault/anchor/tests/readAPI.ts b/compression/cnft-vault/anchor/tests/readAPI.ts index 070203f17..3db19e145 100644 --- a/compression/cnft-vault/anchor/tests/readAPI.ts +++ b/compression/cnft-vault/anchor/tests/readAPI.ts @@ -2,20 +2,21 @@ // as it supports more readAPI functionality // this is just a subset of functions for quick availabiity -import axios from 'axios'; +import axios from "axios"; // you might want to change that to your custom RPC -const RPC_PATH = 'https://rpc-devnet.aws.metaplex.com/'; +const RPC_PATH = "https://rpc-devnet.aws.metaplex.com/"; +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 export async function getAsset(assetId: any, rpcUrl = RPC_PATH): Promise { try { const axiosInstance = axios.create({ baseURL: rpcUrl, }); const response = await axiosInstance.post(rpcUrl, { - jsonrpc: '2.0', - method: 'getAsset', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAsset", + id: "rpd-op-123", params: { id: assetId, }, @@ -26,15 +27,16 @@ export async function getAsset(assetId: any, rpcUrl = RPC_PATH): Promise { } } +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 export async function getAssetProof(assetId: any, rpcUrl = RPC_PATH): Promise { try { const axiosInstance = axios.create({ baseURL: rpcUrl, }); const response = await axiosInstance.post(rpcUrl, { - jsonrpc: '2.0', - method: 'getAssetProof', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAssetProof", + id: "rpd-op-123", params: { id: assetId, }, diff --git a/compression/cnft-vault/anchor/tests/scripts/constants.ts b/compression/cnft-vault/anchor/tests/scripts/constants.ts index 2727afc0c..4ab604bfb 100644 --- a/compression/cnft-vault/anchor/tests/scripts/constants.ts +++ b/compression/cnft-vault/anchor/tests/scripts/constants.ts @@ -3,13 +3,9 @@ import type { CnftVault } from "../../target/types/cnft_vault"; import IDL from "../../target/types/cnft_vault"; import { loadWalletKey } from "../utils"; -export const connection = new anchor.web3.Connection( - "https://api.devnet.solana.com", -); +export const connection = new anchor.web3.Connection("https://api.devnet.solana.com"); export const keypair = loadWalletKey("~/.config/solana/id.json"); export const wallet = new anchor.Wallet(keypair); export const provider = new anchor.AnchorProvider(connection, wallet, {}); -export const programID = new anchor.web3.PublicKey( - "CNftyK7T8udPwYRzZUMWzbh79rKrz9a5GwV2wv7iEHpk", -); +export const programID = new anchor.web3.PublicKey("CNftyK7T8udPwYRzZUMWzbh79rKrz9a5GwV2wv7iEHpk"); export const program = new anchor.Program(IDL, programID, provider); diff --git a/compression/cnft-vault/anchor/tests/scripts/withdraw.ts b/compression/cnft-vault/anchor/tests/scripts/withdraw.ts index 133857d15..73144d840 100644 --- a/compression/cnft-vault/anchor/tests/scripts/withdraw.ts +++ b/compression/cnft-vault/anchor/tests/scripts/withdraw.ts @@ -1,21 +1,24 @@ -import * as anchor from '@anchor-lang/core'; -import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from '@metaplex-foundation/mpl-bubblegum'; -import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from '@solana/spl-account-compression'; -import { getAsset, getAssetProof } from '../readAPI'; -import { decode, mapProof } from '../utils'; +import * as anchor from "@anchor-lang/core"; +import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum"; +import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from "@solana/spl-account-compression"; +import { getAsset, getAssetProof } from "../readAPI"; +import { decode, mapProof } from "../utils"; -import { program, programID } from './constants'; +import { program, programID } from "./constants"; async function main() { - const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from('cNFT-vault', 'utf8')], programID); + const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("cNFT-vault", "utf8")], + programID, + ); - const tree = new anchor.web3.PublicKey('trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B'); + const tree = new anchor.web3.PublicKey("trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B"); - const receiver = new anchor.web3.PublicKey('Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM'); + const receiver = new anchor.web3.PublicKey("Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM"); const [treeAuthority, _bump2] = anchor.web3.PublicKey.findProgramAddressSync([tree.toBuffer()], BUBBLEGUM_PROGRAM_ID); - const assetId = 'DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd'; + const assetId = "DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd"; const asset = await getAsset(assetId); // console.log(res) diff --git a/compression/cnft-vault/anchor/tests/scripts/withdrawTwo.ts b/compression/cnft-vault/anchor/tests/scripts/withdrawTwo.ts index 65785c658..e8f06cf2f 100644 --- a/compression/cnft-vault/anchor/tests/scripts/withdrawTwo.ts +++ b/compression/cnft-vault/anchor/tests/scripts/withdrawTwo.ts @@ -1,28 +1,37 @@ -import * as anchor from '@anchor-lang/core'; -import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from '@metaplex-foundation/mpl-bubblegum'; -import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from '@solana/spl-account-compression'; -import type { AccountMeta } from '@solana/web3.js'; -import { getAsset, getAssetProof } from '../readAPI'; -import { decode, mapProof } from '../utils'; +import * as anchor from "@anchor-lang/core"; +import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum"; +import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from "@solana/spl-account-compression"; +import type { AccountMeta } from "@solana/web3.js"; +import { getAsset, getAssetProof } from "../readAPI"; +import { decode, mapProof } from "../utils"; -import { program, programID } from './constants'; +import { program, programID } from "./constants"; async function main() { // TODO change all of these to your values - const assetId1 = 'DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd'; - const assetId2 = '14JojSTdBZvP7f77rCxB3oQK78skTVD6DiXrXUL4objg'; //"D2CoMLCRfsfv1EAiNbaBHfoU1Sqf1964KXLGxEfyUwWo"; + const assetId1 = "DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd"; + const assetId2 = "14JojSTdBZvP7f77rCxB3oQK78skTVD6DiXrXUL4objg"; //"D2CoMLCRfsfv1EAiNbaBHfoU1Sqf1964KXLGxEfyUwWo"; - const tree1 = new anchor.web3.PublicKey('trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B'); - const tree2 = new anchor.web3.PublicKey('Feywkti8LLBLfxhSGmYgzUBqpq89qehfB1SMTYV1zCu'); + const tree1 = new anchor.web3.PublicKey("trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B"); + const tree2 = new anchor.web3.PublicKey("Feywkti8LLBLfxhSGmYgzUBqpq89qehfB1SMTYV1zCu"); - const receiver1 = new anchor.web3.PublicKey('Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM'); - const receiver2 = new anchor.web3.PublicKey('Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM'); + const receiver1 = new anchor.web3.PublicKey("Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM"); + const receiver2 = new anchor.web3.PublicKey("Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM"); // --- - const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from('cNFT-vault', 'utf8')], programID); + const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("cNFT-vault", "utf8")], + programID, + ); - const [treeAuthority1, _bump2] = anchor.web3.PublicKey.findProgramAddressSync([tree1.toBuffer()], BUBBLEGUM_PROGRAM_ID); - const [treeAuthority2, _bump3] = anchor.web3.PublicKey.findProgramAddressSync([tree2.toBuffer()], BUBBLEGUM_PROGRAM_ID); + const [treeAuthority1, _bump2] = anchor.web3.PublicKey.findProgramAddressSync( + [tree1.toBuffer()], + BUBBLEGUM_PROGRAM_ID, + ); + const [treeAuthority2, _bump3] = anchor.web3.PublicKey.findProgramAddressSync( + [tree2.toBuffer()], + BUBBLEGUM_PROGRAM_ID, + ); const asset1 = await getAsset(assetId1); const asset2 = await getAsset(assetId2); @@ -57,6 +66,7 @@ async function main() { console.log(tx); } +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 function getInstructionData(asset: any, proof: any): [number[], number[], number[], anchor.BN, number, number] { const root = decode(proof.root); const dataHash = decode(asset.compression.data_hash); diff --git a/compression/cnft-vault/anchor/tests/scripts/withdrawWithLookup.ts b/compression/cnft-vault/anchor/tests/scripts/withdrawWithLookup.ts index 20cf63fc4..f3f45097b 100644 --- a/compression/cnft-vault/anchor/tests/scripts/withdrawWithLookup.ts +++ b/compression/cnft-vault/anchor/tests/scripts/withdrawWithLookup.ts @@ -1,6 +1,6 @@ -import * as anchor from '@anchor-lang/core'; -import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from '@metaplex-foundation/mpl-bubblegum'; -import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from '@solana/spl-account-compression'; +import * as anchor from "@anchor-lang/core"; +import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum"; +import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from "@solana/spl-account-compression"; import { type AccountMeta, AddressLookupTableProgram, @@ -10,30 +10,39 @@ import { Transaction, TransactionMessage, VersionedTransaction, -} from '@solana/web3.js'; -import { getAsset, getAssetProof } from '../readAPI'; -import { decode, mapProof } from '../utils'; +} from "@solana/web3.js"; +import { getAsset, getAssetProof } from "../readAPI"; +import { decode, mapProof } from "../utils"; -import { connection, keypair, program, programID } from './constants'; +import { connection, keypair, program, programID } from "./constants"; async function main() { // TODO change all of these to your values - const assetId1 = 'DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd'; - const assetId2 = '14JojSTdBZvP7f77rCxB3oQK78skTVD6DiXrXUL4objg'; //"D2CoMLCRfsfv1EAiNbaBHfoU1Sqf1964KXLGxEfyUwWo"; + const assetId1 = "DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd"; + const assetId2 = "14JojSTdBZvP7f77rCxB3oQK78skTVD6DiXrXUL4objg"; //"D2CoMLCRfsfv1EAiNbaBHfoU1Sqf1964KXLGxEfyUwWo"; - const tree1 = new anchor.web3.PublicKey('trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B'); - const tree2 = new anchor.web3.PublicKey('trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B'); + const tree1 = new anchor.web3.PublicKey("trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B"); + const tree2 = new anchor.web3.PublicKey("trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B"); - const receiver1 = new anchor.web3.PublicKey('Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM'); - const receiver2 = new anchor.web3.PublicKey('Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM'); + const receiver1 = new anchor.web3.PublicKey("Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM"); + const receiver2 = new anchor.web3.PublicKey("Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM"); // --- const lookupTable = await createLookupTable(); - const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from('cNFT-vault', 'utf8')], programID); + const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("cNFT-vault", "utf8")], + programID, + ); - const [treeAuthority1, _bump2] = anchor.web3.PublicKey.findProgramAddressSync([tree1.toBuffer()], BUBBLEGUM_PROGRAM_ID); - const [treeAuthority2, _bump3] = anchor.web3.PublicKey.findProgramAddressSync([tree2.toBuffer()], BUBBLEGUM_PROGRAM_ID); + const [treeAuthority1, _bump2] = anchor.web3.PublicKey.findProgramAddressSync( + [tree1.toBuffer()], + BUBBLEGUM_PROGRAM_ID, + ); + const [treeAuthority2, _bump3] = anchor.web3.PublicKey.findProgramAddressSync( + [tree2.toBuffer()], + BUBBLEGUM_PROGRAM_ID, + ); const asset1 = await getAsset(assetId1); const asset2 = await getAsset(assetId2); @@ -78,7 +87,7 @@ async function main() { const lookupTableAccount = await connection.getAddressLookupTable(lookupTable).then((res) => res.value); if (!lookupTableAccount) { - console.log('could not fetch ATL!'); + console.log("could not fetch ATL!"); return; } @@ -97,6 +106,7 @@ async function main() { console.log(txid); } +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 function getInstructionData(asset: any, proof: any): [number[], number[], number[], anchor.BN, number, number] { const root = decode(proof.root); const dataHash = decode(asset.compression.data_hash); @@ -121,10 +131,10 @@ async function extendLookupTable(lookupTableAddress: PublicKey, proofHashes: Pub tx.add(extendInstruction); const sx = await sendAndConfirmTransaction(connection, tx, [keypair], { - commitment: 'finalized', + commitment: "finalized", }); console.log(sx); - console.log('ALT extended!'); + console.log("ALT extended!"); } async function createLookupTable(): Promise { @@ -155,10 +165,10 @@ async function createLookupTable(): Promise { tx.add(lookupTableInst).add(extendInstruction); const sx = await sendAndConfirmTransaction(connection, tx, [keypair], { - commitment: 'finalized', + commitment: "finalized", }); console.log(sx); - console.log('ALT created'); + console.log("ALT created"); return lookupTableAddress; } diff --git a/compression/cnft-vault/anchor/tests/tests.ts b/compression/cnft-vault/anchor/tests/tests.ts index 28031d448..b378ecbbe 100644 --- a/compression/cnft-vault/anchor/tests/tests.ts +++ b/compression/cnft-vault/anchor/tests/tests.ts @@ -1,31 +1,37 @@ -import * as anchor from '@anchor-lang/core'; -import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from '@metaplex-foundation/mpl-bubblegum'; -import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from '@solana/spl-account-compression'; -import type { AccountMeta } from '@solana/web3.js'; -import { type CnftVault } from '../target/types/cnft_vault'; -import { getAsset, getAssetProof } from './readAPI'; -import { decode, mapProof } from './utils'; - -describe('cNFT Vault', () => { +import * as anchor from "@anchor-lang/core"; +import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum"; +import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from "@solana/spl-account-compression"; +import type { AccountMeta } from "@solana/web3.js"; +import type { CnftVault } from "../target/types/cnft_vault"; +import { getAsset, getAssetProof } from "./readAPI"; +import { decode, mapProof } from "./utils"; + +describe("cNFT Vault", () => { const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); const payer = provider.wallet as anchor.Wallet; const program = anchor.workspace.CnftVault as anchor.Program; - const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from('cNFT-vault', 'utf8')], program.programId); + const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("cNFT-vault", "utf8")], + program.programId, + ); console.log(`Vault address: ${vaultPDA.toBase58()}`); - it('Withdraw a cNFT!', async () => { + it("Withdraw a cNFT!", async () => { // we expect the cNFT to already be in the vault // you can send it there (to vaultPDA) using any regular wallet // the cNFT has the following asset id - const assetId = 'DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd'; // TODO + const assetId = "DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd"; // TODO // and is compressed in the following tree - const tree = new anchor.web3.PublicKey('trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B'); // TODO + const tree = new anchor.web3.PublicKey("trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B"); // TODO const receiver = payer.publicKey; // you can define any pubkey as the receiver here - const [treeAuthority, _bump2] = anchor.web3.PublicKey.findProgramAddressSync([tree.toBuffer()], BUBBLEGUM_PROGRAM_ID); + const [treeAuthority, _bump2] = anchor.web3.PublicKey.findProgramAddressSync( + [tree.toBuffer()], + BUBBLEGUM_PROGRAM_ID, + ); const asset = await getAsset(assetId); @@ -53,24 +59,30 @@ describe('cNFT Vault', () => { .remainingAccounts(proofPathAsAccounts) .rpc(); - console.log('Success!'); + console.log("Success!"); console.log(` Tx Signature: ${sx}`); }); - it('Withdraw two cNFTs!', async () => { + it("Withdraw two cNFTs!", async () => { // TODO change all of these to your values - const assetId1 = 'DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd'; - const assetId2 = '14JojSTdBZvP7f77rCxB3oQK78skTVD6DiXrXUL4objg'; + const assetId1 = "DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd"; + const assetId2 = "14JojSTdBZvP7f77rCxB3oQK78skTVD6DiXrXUL4objg"; - const tree1 = new anchor.web3.PublicKey('trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B'); - const tree2 = new anchor.web3.PublicKey('Feywkti8LLBLfxhSGmYgzUBqpq89qehfB1SMTYV1zCu'); + const tree1 = new anchor.web3.PublicKey("trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B"); + const tree2 = new anchor.web3.PublicKey("Feywkti8LLBLfxhSGmYgzUBqpq89qehfB1SMTYV1zCu"); - const receiver1 = new anchor.web3.PublicKey('Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM'); - const receiver2 = new anchor.web3.PublicKey('Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM'); + const receiver1 = new anchor.web3.PublicKey("Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM"); + const receiver2 = new anchor.web3.PublicKey("Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM"); // --- - const [treeAuthority1, _bump2] = anchor.web3.PublicKey.findProgramAddressSync([tree1.toBuffer()], BUBBLEGUM_PROGRAM_ID); - const [treeAuthority2, _bump3] = anchor.web3.PublicKey.findProgramAddressSync([tree2.toBuffer()], BUBBLEGUM_PROGRAM_ID); + const [treeAuthority1, _bump2] = anchor.web3.PublicKey.findProgramAddressSync( + [tree1.toBuffer()], + BUBBLEGUM_PROGRAM_ID, + ); + const [treeAuthority2, _bump3] = anchor.web3.PublicKey.findProgramAddressSync( + [tree2.toBuffer()], + BUBBLEGUM_PROGRAM_ID, + ); const asset1 = await getAsset(assetId1); const asset2 = await getAsset(assetId2); @@ -102,11 +114,12 @@ describe('cNFT Vault', () => { }) .remainingAccounts(remainingAccounts) .rpc(); - console.log('Success!'); + console.log("Success!"); console.log(` Tx Signature: ${sx}`); }); }); +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 function getInstructionData(asset: any, proof: any): [number[], number[], number[], anchor.BN, number, number] { const root = decode(proof.root); const dataHash = decode(asset.compression.data_hash); diff --git a/compression/cnft-vault/anchor/tests/utils.ts b/compression/cnft-vault/anchor/tests/utils.ts index 43759dd36..70aa141d9 100644 --- a/compression/cnft-vault/anchor/tests/utils.ts +++ b/compression/cnft-vault/anchor/tests/utils.ts @@ -1,9 +1,9 @@ -import { type AccountMeta, Keypair, PublicKey } from '@solana/web3.js'; +import { type AccountMeta, Keypair, PublicKey } from "@solana/web3.js"; -import * as bs58 from 'bs58'; +import * as bs58 from "bs58"; export function loadWalletKey(keypairFile: string): Keypair { - const fs = require('node:fs'); + const fs = require("node:fs"); return Keypair.fromSecretKey(new Uint8Array(JSON.parse(fs.readFileSync(keypairFile).toString()))); } @@ -19,7 +19,7 @@ function bufferToArray(buffer: Buffer): number[] { } export const mapProof = (assetProof: { proof: string[] }): AccountMeta[] => { if (!assetProof.proof || assetProof.proof.length === 0) { - throw new Error('Proof is empty'); + throw new Error("Proof is empty"); } return assetProof.proof.map((node) => ({ pubkey: new PublicKey(node), diff --git a/compression/cutils/anchor/Anchor.toml b/compression/cutils/anchor/Anchor.toml index 1e5158a3c..20bad88e1 100644 --- a/compression/cutils/anchor/Anchor.toml +++ b/compression/cutils/anchor/Anchor.toml @@ -5,14 +5,14 @@ solana_version = "3.1.8" resolution = true skip-lint = false -[programs.devnet] +[programs.localnet] cutils = "BuFyrgRYzg2nPhqYrxZ7d9uYUs4VXtxH71U8EcoAfTQZ" # [registry] section removed — no longer used in Anchor 1.0 [provider] -cluster = "devnet" -wallet = "~/.config/solana/test.json" +cluster = "localnet" +wallet = "~/.config/solana/id.json" [scripts] test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" diff --git a/compression/cutils/anchor/package.json b/compression/cutils/anchor/package.json index d0a67bfdb..3ccfe05d8 100644 --- a/compression/cutils/anchor/package.json +++ b/compression/cutils/anchor/package.json @@ -1,27 +1,27 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@metaplex-foundation/js": "^0.19.4", - "@metaplex-foundation/mpl-bubblegum": "^0.7.0", - "@solana/spl-account-compression": "^0.1.8", - "@solana/spl-token": "^0.3.8", - "@solana/web3.js": "^1.98.4", - "axios": "^1.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "ts-node": "^10.9.1", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@metaplex-foundation/js": "^0.19.4", + "@metaplex-foundation/mpl-bubblegum": "^0.7.0", + "@solana/spl-account-compression": "^0.1.8", + "@solana/spl-token": "^0.3.8", + "@solana/web3.js": "^1.98.4", + "axios": "^1.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "ts-node": "^10.9.1", + "typescript": "^5.3.3" + } } diff --git a/compression/cutils/anchor/pnpm-lock.yaml b/compression/cutils/anchor/pnpm-lock.yaml index 1d5ffad49..138b25f84 100644 --- a/compression/cutils/anchor/pnpm-lock.yaml +++ b/compression/cutils/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) '@metaplex-foundation/js': specifier: ^0.19.4 version: 0.19.5(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@6.0.6) @@ -60,18 +60,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.6': @@ -1692,16 +1692,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 @@ -1719,7 +1719,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.6': dependencies: diff --git a/compression/cutils/anchor/programs/cutils/Cargo.toml b/compression/cutils/anchor/programs/cutils/Cargo.toml index c2b4aa431..3f5241e81 100644 --- a/compression/cutils/anchor/programs/cutils/Cargo.toml +++ b/compression/cutils/anchor/programs/cutils/Cargo.toml @@ -20,8 +20,7 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" +anchor-lang = "1.0.0" # mpl-bubblegum and spl-account-compression removed: they depend on solana-program 2.x # which is incompatible with Anchor 1.0's solana 3.x types. CPI calls are built manually # using raw invoke() with hardcoded program IDs and discriminators. Bubblegum types @@ -29,7 +28,6 @@ anchor-lang = "1.0.0-rc.5" borsh = "1" sha2 = "0.10" sha3 = "0.10" -ahash = "=0.8.7" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/compression/cutils/anchor/programs/cutils/src/actions/mint.rs b/compression/cutils/anchor/programs/cutils/src/actions/mint.rs index f8b879193..a1a179034 100644 --- a/compression/cutils/anchor/programs/cutils/src/actions/mint.rs +++ b/compression/cutils/anchor/programs/cutils/src/actions/mint.rs @@ -67,7 +67,7 @@ pub struct Mint<'info> { #[derive(Clone, AnchorSerialize, AnchorDeserialize)] pub struct MintParams { - uri: String, + pub uri: String, } impl Mint<'_> { diff --git a/compression/cutils/anchor/programs/cutils/src/actions/verify.rs b/compression/cutils/anchor/programs/cutils/src/actions/verify.rs index 87f282b2e..7117f71bf 100644 --- a/compression/cutils/anchor/programs/cutils/src/actions/verify.rs +++ b/compression/cutils/anchor/programs/cutils/src/actions/verify.rs @@ -18,11 +18,11 @@ pub struct Verify<'info> { #[derive(Clone, AnchorSerialize, AnchorDeserialize)] pub struct VerifyParams { - root: [u8; 32], - data_hash: [u8; 32], - creator_hash: [u8; 32], - nonce: u64, - index: u32, + pub root: [u8; 32], + pub data_hash: [u8; 32], + pub creator_hash: [u8; 32], + pub nonce: u64, + pub index: u32, } impl Verify<'_> { diff --git a/compression/cutils/anchor/tests/setup.ts b/compression/cutils/anchor/tests/setup.ts index d17721ff7..21b0de775 100644 --- a/compression/cutils/anchor/tests/setup.ts +++ b/compression/cutils/anchor/tests/setup.ts @@ -1,19 +1,19 @@ -import type { CreateMetadataAccountArgsV3 } from '@metaplex-foundation/mpl-token-metadata'; -import type { ValidDepthSizePair } from '@solana/spl-account-compression'; -import { Connection, Keypair } from '@solana/web3.js'; -import { createCollection, createTree } from './utils/compression'; -import { loadOrGenerateKeypair, savePublicKeyToFile } from './utils/helpers'; +import type { CreateMetadataAccountArgsV3 } from "@metaplex-foundation/mpl-token-metadata"; +import type { ValidDepthSizePair } from "@solana/spl-account-compression"; +import { Connection, Keypair } from "@solana/web3.js"; +import { createCollection, createTree } from "./utils/compression"; +import { loadOrGenerateKeypair, savePublicKeyToFile } from "./utils/helpers"; async function _setup() { - const rpc = 'https://api.devnet.solana.com'; - const connection = new Connection(rpc, 'confirmed'); + const rpc = "https://api.devnet.solana.com"; + const connection = new Connection(rpc, "confirmed"); // Collection auth and treeCreator - const payer = loadOrGenerateKeypair('payer'); + const payer = loadOrGenerateKeypair("payer"); // Airdrop await connection.requestAirdrop(payer.publicKey, 1 * 10 ** 9); - console.log('Payer address:', payer.publicKey.toBase58()); + console.log("Payer address:", payer.publicKey.toBase58()); const treeKeypair = Keypair.generate(); const maxDepthSizePair: ValidDepthSizePair = { @@ -24,14 +24,14 @@ async function _setup() { const tree = await createTree(connection, payer, treeKeypair, maxDepthSizePair, canopyDepth); // locally save the addresses for demo - savePublicKeyToFile('treeAddress', tree.treeAddress); + savePublicKeyToFile("treeAddress", tree.treeAddress); const collectionMetadataV3: CreateMetadataAccountArgsV3 = { data: { - name: 'Super Sweet NFT Collection', - symbol: 'SSNC', + name: "Super Sweet NFT Collection", + symbol: "SSNC", // specific json metadata for the collection - uri: 'https://supersweetcollection.notarealurl/collection.json', + uri: "https://supersweetcollection.notarealurl/collection.json", sellerFeeBasisPoints: 100, creators: [ { @@ -51,7 +51,7 @@ async function _setup() { const collection = await createCollection(connection, payer, collectionMetadataV3); // locally save the addresses for the demo - savePublicKeyToFile('collectionMint', collection.mint); + savePublicKeyToFile("collectionMint", collection.mint); } // setup() diff --git a/compression/cutils/anchor/tests/tests.ts b/compression/cutils/anchor/tests/tests.ts index ca62754f9..4acbea02c 100644 --- a/compression/cutils/anchor/tests/tests.ts +++ b/compression/cutils/anchor/tests/tests.ts @@ -1,10 +1,10 @@ -import * as anchor from '@anchor-lang/core'; -import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from '@metaplex-foundation/mpl-bubblegum/dist/src/generated'; -import type { Cutils } from '../target/types/cutils'; -import { loadOrGenerateKeypair, loadPublicKeysFromFile } from './utils/helpers'; -import { getAccounts } from './utils/utils'; +import * as anchor from "@anchor-lang/core"; +import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum/dist/src/generated"; +import type { Cutils } from "../target/types/cutils"; +import { loadOrGenerateKeypair, loadPublicKeysFromFile } from "./utils/helpers"; +import { getAccounts } from "./utils/utils"; -describe('cutils', () => { +describe("cutils", () => { const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); @@ -12,16 +12,16 @@ describe('cutils', () => { // NFT metadata pointer // TODO change - const uri = 'https://arweave.net/nVRvZDaOk5YAdr4ZBEeMjOVhynuv8P3vywvuN5sYSPo'; + const uri = "https://arweave.net/nVRvZDaOk5YAdr4ZBEeMjOVhynuv8P3vywvuN5sYSPo"; - const payer = loadOrGenerateKeypair('payer'); + const payer = loadOrGenerateKeypair("payer"); // cNFT receiver - const testWallet = loadOrGenerateKeypair('testWallet'); + const testWallet = loadOrGenerateKeypair("testWallet"); const { collectionMint, treeAddress } = loadPublicKeysFromFile(); - it('Mint!', async () => { + it("Mint!", async () => { const tx = await program.methods .mint({ uri }) .accounts({ diff --git a/compression/cutils/anchor/tests/utils/compression.ts b/compression/cutils/anchor/tests/utils/compression.ts index 87c710718..77eff4022 100644 --- a/compression/cutils/anchor/tests/utils/compression.ts +++ b/compression/cutils/anchor/tests/utils/compression.ts @@ -5,20 +5,32 @@ import { createCreateTreeInstruction, createMintToCollectionV1Instruction, type MetadataArgs, -} from '@metaplex-foundation/mpl-bubblegum'; +} from "@metaplex-foundation/mpl-bubblegum"; import { type CreateMetadataAccountArgsV3, createCreateMasterEditionV3Instruction, createCreateMetadataAccountV3Instruction, createSetCollectionSizeInstruction, PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID, -} from '@metaplex-foundation/mpl-token-metadata'; -import { createAllocTreeIx, SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID, type ValidDepthSizePair } from '@solana/spl-account-compression'; -import { createAccount, createMint, mintTo, TOKEN_PROGRAM_ID } from '@solana/spl-token'; -import { type Connection, type Keypair, PublicKey, sendAndConfirmTransaction, Transaction, type TransactionInstruction } from '@solana/web3.js'; +} from "@metaplex-foundation/mpl-token-metadata"; +import { + createAllocTreeIx, + SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, + SPL_NOOP_PROGRAM_ID, + type ValidDepthSizePair, +} from "@solana/spl-account-compression"; +import { createAccount, createMint, mintTo, TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { + type Connection, + type Keypair, + PublicKey, + sendAndConfirmTransaction, + Transaction, + type TransactionInstruction, +} from "@solana/web3.js"; // import local helper functions -import { explorerURL, extractSignatureFromFailedTransaction } from './helpers'; +import { explorerURL, extractSignatureFromFailedTransaction } from "./helpers"; /* Helper function to create a merkle tree on chain, including allocating @@ -31,16 +43,25 @@ export async function createTree( maxDepthSizePair: ValidDepthSizePair, canopyDepth = 0, ) { - console.log('Creating a new Merkle tree...'); - console.log('treeAddress:', treeKeypair.publicKey.toBase58()); + console.log("Creating a new Merkle tree..."); + console.log("treeAddress:", treeKeypair.publicKey.toBase58()); // derive the tree's authority (PDA), owned by Bubblegum - const [treeAuthority, _bump] = PublicKey.findProgramAddressSync([treeKeypair.publicKey.toBuffer()], BUBBLEGUM_PROGRAM_ID); - console.log('treeAuthority:', treeAuthority.toBase58()); + const [treeAuthority, _bump] = PublicKey.findProgramAddressSync( + [treeKeypair.publicKey.toBuffer()], + BUBBLEGUM_PROGRAM_ID, + ); + console.log("treeAuthority:", treeAuthority.toBase58()); // allocate the tree's account on chain with the `space` // NOTE: this will compute the space needed to store the tree on chain (and the lamports required to store it) - const allocTreeIx = await createAllocTreeIx(connection, treeKeypair.publicKey, payer.publicKey, maxDepthSizePair, canopyDepth); + const allocTreeIx = await createAllocTreeIx( + connection, + treeKeypair.publicKey, + payer.publicKey, + maxDepthSizePair, + canopyDepth, + ); // create the instruction to actually create the tree const createTreeIx = createCreateTreeInstruction( @@ -65,7 +86,7 @@ export async function createTree( // create and send the transaction to initialize the tree const tx = new Transaction().add(allocTreeIx).add(createTreeIx); tx.feePayer = payer.publicKey; - console.log('tx'); + console.log("tx"); // send the transaction const txSignature = await sendAndConfirmTransaction( @@ -74,18 +95,19 @@ export async function createTree( // ensuring the `treeKeypair` PDA and the `payer` are BOTH signers [treeKeypair, payer], { - commitment: 'confirmed', + commitment: "confirmed", skipPreflight: true, }, ); - console.log('\nMerkle tree created successfully!'); + console.log("\nMerkle tree created successfully!"); console.log(explorerURL({ txSignature })); // return useful info return { treeAuthority, treeAddress: treeKeypair.publicKey }; + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 } catch (err: any) { - console.error('\nFailed to create merkle tree:', err); + console.error("\nFailed to create merkle tree:", err); // log a block explorer link for the failed transaction await extractSignatureFromFailedTransaction(connection, err); @@ -98,7 +120,11 @@ export async function createTree( * Create an NFT collection on-chain, using the regular Metaplex standards * with the `payer` as the authority */ -export async function createCollection(connection: Connection, payer: Keypair, metadataV3: CreateMetadataAccountArgsV3) { +export async function createCollection( + connection: Connection, + payer: Keypair, + metadataV3: CreateMetadataAccountArgsV3, +) { // create and initialize the SPL token mint console.log("Creating the collection's mint..."); const mint = await createMint( @@ -111,10 +137,10 @@ export async function createCollection(connection: Connection, payer: Keypair, m // decimals - use `0` for NFTs since they are non-fungible 0, ); - console.log('Mint address:', mint.toBase58()); + console.log("Mint address:", mint.toBase58()); // create the token account - console.log('Creating a token account...'); + console.log("Creating a token account..."); const tokenAccount = await createAccount( connection, payer, @@ -122,10 +148,10 @@ export async function createCollection(connection: Connection, payer: Keypair, m payer.publicKey, // undefined, undefined, ); - console.log('Token account:', tokenAccount.toBase58()); + console.log("Token account:", tokenAccount.toBase58()); // mint 1 token () - console.log('Minting 1 token for the collection...'); + console.log("Minting 1 token for the collection..."); const _mintSig = await mintTo( connection, payer, @@ -143,10 +169,10 @@ export async function createCollection(connection: Connection, payer: Keypair, m // derive the PDA for the metadata account const [metadataAccount, _bump] = PublicKey.findProgramAddressSync( - [Buffer.from('metadata', 'utf8'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], + [Buffer.from("metadata", "utf8"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], TOKEN_METADATA_PROGRAM_ID, ); - console.log('Metadata account:', metadataAccount.toBase58()); + console.log("Metadata account:", metadataAccount.toBase58()); // create an instruction to create the metadata account const createMetadataIx = createCreateMetadataAccountV3Instruction( @@ -164,10 +190,15 @@ export async function createCollection(connection: Connection, payer: Keypair, m // derive the PDA for the metadata account const [masterEditionAccount, _bump2] = PublicKey.findProgramAddressSync( - [Buffer.from('metadata', 'utf8'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer(), Buffer.from('edition', 'utf8')], + [ + Buffer.from("metadata", "utf8"), + TOKEN_METADATA_PROGRAM_ID.toBuffer(), + mint.toBuffer(), + Buffer.from("edition", "utf8"), + ], TOKEN_METADATA_PROGRAM_ID, ); - console.log('Master edition account:', masterEditionAccount.toBase58()); + console.log("Master edition account:", masterEditionAccount.toBase58()); // create an instruction to create the metadata account const createMasterEditionIx = createCreateMasterEditionV3Instruction( @@ -205,14 +236,14 @@ export async function createCollection(connection: Connection, payer: Keypair, m // send the transaction to the cluster const txSignature = await sendAndConfirmTransaction(connection, tx, [payer], { - commitment: 'confirmed', + commitment: "confirmed", skipPreflight: true, }); - console.log('\nCollection successfully created!'); + console.log("\nCollection successfully created!"); console.log(explorerURL({ txSignature })); } catch (err) { - console.error('\nFailed to create collection:', err); + console.error("\nFailed to create collection:", err); // log a block explorer link for the failed transaction await extractSignatureFromFailedTransaction(connection, err); @@ -243,7 +274,7 @@ export async function mintCompressedNFT( // derive a PDA (owned by Bubblegum) to act as the signer of the compressed minting const [bubblegumSigner, _bump2] = PublicKey.findProgramAddressSync( // `collection_cpi` is a custom prefix required by the Bubblegum program - [Buffer.from('collection_cpi', 'utf8')], + [Buffer.from("collection_cpi", "utf8")], BUBBLEGUM_PROGRAM_ID, ); @@ -270,8 +301,8 @@ export async function mintCompressedNFT( */ const computedDataHash = new PublicKey(computeDataHash(metadataArgs)).toBase58(); const computedCreatorHash = new PublicKey(computeCreatorHash(metadataArgs.creators)).toBase58(); - console.log('computedDataHash:', computedDataHash); - console.log('computedCreatorHash:', computedCreatorHash); + console.log("computedDataHash:", computedDataHash); + console.log("computedCreatorHash:", computedCreatorHash); /* Add a single mint to collection instruction @@ -327,16 +358,16 @@ export async function mintCompressedNFT( // send the transaction to the cluster const txSignature = await sendAndConfirmTransaction(connection, tx, [payer], { - commitment: 'confirmed', + commitment: "confirmed", skipPreflight: true, }); - console.log('\nSuccessfully minted the compressed NFT!'); + console.log("\nSuccessfully minted the compressed NFT!"); console.log(explorerURL({ txSignature })); return txSignature; } catch (err) { - console.error('\nFailed to mint compressed NFT:', err); + console.error("\nFailed to mint compressed NFT:", err); // log a block explorer link for the failed transaction await extractSignatureFromFailedTransaction(connection, err); diff --git a/compression/cutils/anchor/tests/utils/helpers.ts b/compression/cutils/anchor/tests/utils/helpers.ts index ffe3ad8c4..a793000c9 100644 --- a/compression/cutils/anchor/tests/utils/helpers.ts +++ b/compression/cutils/anchor/tests/utils/helpers.ts @@ -1,26 +1,26 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import { type Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js'; +import fs from "node:fs"; +import path from "node:path"; +import { type Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js"; // define some default locations -const DEFAULT_KEY_DIR_NAME = '.local_keys'; -const DEFAULT_PUBLIC_KEY_FILE = 'keys.json'; -const DEFAULT_DEMO_DATA_FILE = 'demo.json'; +const DEFAULT_KEY_DIR_NAME = ".local_keys"; +const DEFAULT_PUBLIC_KEY_FILE = "keys.json"; +const DEFAULT_DEMO_DATA_FILE = "demo.json"; /* Load locally stored PublicKey addresses */ export function loadPublicKeysFromFile(absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_PUBLIC_KEY_FILE}`) { try { - if (!absPath) throw Error('No path provided'); - if (!fs.existsSync(absPath)) throw Error('File does not exist.'); + if (!absPath) throw Error("No path provided"); + if (!fs.existsSync(absPath)) throw Error("File does not exist."); // load the public keys from the file - const data = JSON.parse(fs.readFileSync(absPath, { encoding: 'utf-8' })) || {}; + const data = JSON.parse(fs.readFileSync(absPath, { encoding: "utf-8" })) || {}; // convert all loaded keyed values into valid public keys for (const [key, value] of Object.entries(data)) { - data[key] = new PublicKey(value as string) ?? ''; + data[key] = new PublicKey(value as string) ?? ""; } return data; @@ -34,23 +34,28 @@ export function loadPublicKeysFromFile(absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFA /* Locally save a demo data to the filesystem for later retrieval */ -export function saveDemoDataToFile(name: string, newData: any, absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_DEMO_DATA_FILE}`) { +export function saveDemoDataToFile( + name: string, + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 + newData: any, + absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_DEMO_DATA_FILE}`, +) { try { let data: object = {}; // fetch all the current values, when the storage file exists - if (fs.existsSync(absPath)) data = JSON.parse(fs.readFileSync(absPath, { encoding: 'utf-8' })) || {}; + if (fs.existsSync(absPath)) data = JSON.parse(fs.readFileSync(absPath, { encoding: "utf-8" })) || {}; data = { ...data, [name]: newData }; // actually save the data to the file fs.writeFileSync(absPath, JSON.stringify(data), { - encoding: 'utf-8', + encoding: "utf-8", }); return data; } catch (_err) { - console.warn('Unable to save to file'); + console.warn("Unable to save to file"); // console.warn(err); } @@ -61,23 +66,29 @@ export function saveDemoDataToFile(name: string, newData: any, absPath = `${DEFA /* Locally save a PublicKey addresses to the filesystem for later retrieval */ -export function savePublicKeyToFile(name: string, publicKey: PublicKey, absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_PUBLIC_KEY_FILE}`) { +export function savePublicKeyToFile( + name: string, + publicKey: PublicKey, + absPath = `${DEFAULT_KEY_DIR_NAME}/${DEFAULT_PUBLIC_KEY_FILE}`, +) { try { // if (!absPath) throw Error("No path provided"); // if (!fs.existsSync(absPath)) throw Error("File does not exist."); // fetch all the current values + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 let data: any = loadPublicKeysFromFile(absPath); // convert all loaded keyed values from PublicKeys to strings for (const [key, value] of Object.entries(data)) { + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 data[key as any] = (value as PublicKey).toBase58(); } data = { ...data, [name]: publicKey.toBase58() }; // actually save the data to the file fs.writeFileSync(absPath, JSON.stringify(data), { - encoding: 'utf-8', + encoding: "utf-8", }); // reload the keys for sanity @@ -85,7 +96,7 @@ export function savePublicKeyToFile(name: string, publicKey: PublicKey, absPath return data; } catch (_err) { - console.warn('Unable to save to file'); + console.warn("Unable to save to file"); } // always return an object return {}; @@ -96,16 +107,16 @@ export function savePublicKeyToFile(name: string, publicKey: PublicKey, absPath */ export function loadKeypairFromFile(absPath: string) { try { - if (!absPath) throw Error('No path provided'); - if (!fs.existsSync(absPath)) throw Error('File does not exist.'); + if (!absPath) throw Error("No path provided"); + if (!fs.existsSync(absPath)) throw Error("File does not exist."); // load the keypair from the file - const keyfileBytes = JSON.parse(fs.readFileSync(absPath, { encoding: 'utf-8' })); + const keyfileBytes = JSON.parse(fs.readFileSync(absPath, { encoding: "utf-8" })); // parse the loaded secretKey into a valid keypair const keypair = Keypair.fromSecretKey(new Uint8Array(keyfileBytes)); return keypair; } catch (err) { - console.error('loadKeypairFromFile:', err); + console.error("loadKeypairFromFile:", err); throw err; } } @@ -125,7 +136,7 @@ export function saveKeypairToFile(keypair: Keypair, relativeFileName: string, di // write the `secretKey` value as a string fs.writeFileSync(fileName, `[${keypair.secretKey.toString()}]`, { - encoding: 'utf-8', + encoding: "utf-8", }); return fileName; @@ -147,7 +158,7 @@ export function loadOrGenerateKeypair(fileName: string, dirName: string = DEFAUL return keypair; } catch (err) { - console.error('loadOrGenerateKeypair:', err); + console.error("loadOrGenerateKeypair:", err); throw err; } } @@ -162,17 +173,17 @@ export function explorerURL({ }: { address?: string; txSignature?: string; - cluster?: 'devnet' | 'testnet' | 'mainnet' | 'mainnet-beta'; + cluster?: "devnet" | "testnet" | "mainnet" | "mainnet-beta"; }) { let baseUrl: string; // if (address) baseUrl = `https://explorer.solana.com/address/${address}`; else if (txSignature) baseUrl = `https://explorer.solana.com/tx/${txSignature}`; - else return '[unknown]'; + else return "[unknown]"; // auto append the desired search params const url = new URL(baseUrl); - url.searchParams.append('cluster', cluster || 'devnet'); + url.searchParams.append("cluster", cluster || "devnet"); return `${url.toString()}\n`; } @@ -190,7 +201,7 @@ export async function airdropOnLowBalance(connection: Connection, keypair: Keypa if (forceAirdrop === true || balance < MIN_BALANCE_TO_AIRDROP) { console.log(`Requesting airdrop of 1 SOL to ${keypair.publicKey.toBase58()}...`); await connection.requestAirdrop(keypair.publicKey, LAMPORTS_PER_SOL).then((sig) => { - console.log('Tx signature:', sig); + console.log("Tx signature:", sig); // balance = balance + LAMPORTS_PER_SOL; }); @@ -206,11 +217,14 @@ export async function airdropOnLowBalance(connection: Connection, keypair: Keypa /* Helper function to extract a transaction signature from a failed transaction's error message */ +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 export async function extractSignatureFromFailedTransaction(connection: Connection, err: any, fetchLogs?: boolean) { if (err?.signature) return err.signature; // extract the failed transaction's signature - const failedSig = new RegExp(/^((.*)?Error: )?(Transaction|Signature) ([A-Z0-9]{32,}) /gim).exec(err?.message?.toString())?.[4]; + const failedSig = new RegExp(/^((.*)?Error: )?(Transaction|Signature) ([A-Z0-9]{32,}) /gim).exec( + err?.message?.toString(), + )?.[4]; // ensure a signature was found if (failedSig) { @@ -222,14 +236,14 @@ export async function extractSignatureFromFailedTransaction(connection: Connecti }) .then((tx) => { console.log(`\n==== Transaction logs for ${failedSig} ====`); - console.log(explorerURL({ txSignature: failedSig }), ''); - console.log(tx?.meta?.logMessages ?? 'No log messages provided by RPC'); - console.log('==== END LOGS ====\n'); + console.log(explorerURL({ txSignature: failedSig }), ""); + console.log(tx?.meta?.logMessages ?? "No log messages provided by RPC"); + console.log("==== END LOGS ====\n"); }); else { - console.log('\n========================================'); + console.log("\n========================================"); console.log(explorerURL({ txSignature: failedSig })); - console.log('========================================\n'); + console.log("========================================\n"); } } @@ -254,7 +268,7 @@ export function numberFormatter(num: number, forceDecimals = false) { Display a separator in the console, with our without a message */ export function printConsoleSeparator(message?: string) { - console.log('\n==============================================='); - console.log('===============================================\n'); + console.log("\n==============================================="); + console.log("===============================================\n"); if (message) console.log(message); } diff --git a/compression/cutils/anchor/tests/utils/readAPI.ts b/compression/cutils/anchor/tests/utils/readAPI.ts index 3562d91c6..7c324845e 100644 --- a/compression/cutils/anchor/tests/utils/readAPI.ts +++ b/compression/cutils/anchor/tests/utils/readAPI.ts @@ -2,20 +2,21 @@ // as it supports more readAPI functionality // this is just a subset of functions for quick availabiity -import axios from 'axios'; +import axios from "axios"; //TODO insert -const RPC_PATH = ''; +const RPC_PATH = ""; +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 export async function getAsset(assetId: any, rpcUrl = RPC_PATH): Promise { try { const axiosInstance = axios.create({ baseURL: rpcUrl, }); const response = await axiosInstance.post(rpcUrl, { - jsonrpc: '2.0', - method: 'getAsset', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAsset", + id: "rpd-op-123", params: { id: assetId, }, @@ -26,15 +27,16 @@ export async function getAsset(assetId: any, rpcUrl = RPC_PATH): Promise { } } +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 export async function getAssetProof(assetId: any, rpcUrl = RPC_PATH): Promise { try { const axiosInstance = axios.create({ baseURL: rpcUrl, }); const response = await axiosInstance.post(rpcUrl, { - jsonrpc: '2.0', - method: 'getAssetProof', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAssetProof", + id: "rpd-op-123", params: { id: assetId, }, diff --git a/compression/cutils/anchor/tests/utils/utils.ts b/compression/cutils/anchor/tests/utils/utils.ts index 74206b75e..4e3001eee 100644 --- a/compression/cutils/anchor/tests/utils/utils.ts +++ b/compression/cutils/anchor/tests/utils/utils.ts @@ -1,8 +1,8 @@ -import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from '@metaplex-foundation/mpl-bubblegum/dist/src/generated'; -import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from '@metaplex-foundation/mpl-token-metadata/dist/src/generated'; -import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from '@solana/spl-account-compression'; -import { type AccountMeta, PublicKey, SystemProgram } from '@solana/web3.js'; -import * as bs58 from 'bs58'; +import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum/dist/src/generated"; +import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata/dist/src/generated"; +import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from "@solana/spl-account-compression"; +import { type AccountMeta, PublicKey, SystemProgram } from "@solana/web3.js"; +import * as bs58 from "bs58"; export function decode(stuff: string) { return bufferToArray(bs58.decode(stuff)); @@ -16,7 +16,7 @@ function bufferToArray(buffer: Buffer): number[] { } export const mapProof = (assetProof: { proof: string[] }): AccountMeta[] => { if (!assetProof.proof || assetProof.proof.length === 0) { - throw new Error('Proof is empty'); + throw new Error("Proof is empty"); } return assetProof.proof.map((node) => ({ pubkey: new PublicKey(node), @@ -32,19 +32,24 @@ export function getAccounts(collectionMint: PublicKey, tree: PublicKey) { // derive a PDA (owned by Bubblegum) to act as the signer of the compressed minting const [bubblegumSigner] = PublicKey.findProgramAddressSync( // `collection_cpi` is a custom prefix required by the Bubblegum program - [Buffer.from('collection_cpi', 'utf8')], + [Buffer.from("collection_cpi", "utf8")], BUBBLEGUM_PROGRAM_ID, ); // collection metadata account const [metadataAccount] = PublicKey.findProgramAddressSync( - [Buffer.from('metadata', 'utf8'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), collectionMint.toBuffer()], + [Buffer.from("metadata", "utf8"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), collectionMint.toBuffer()], TOKEN_METADATA_PROGRAM_ID, ); // collection master edition const [masterEditionAccount] = PublicKey.findProgramAddressSync( - [Buffer.from('metadata', 'utf8'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), collectionMint.toBuffer(), Buffer.from('edition', 'utf8')], + [ + Buffer.from("metadata", "utf8"), + TOKEN_METADATA_PROGRAM_ID.toBuffer(), + collectionMint.toBuffer(), + Buffer.from("edition", "utf8"), + ], TOKEN_METADATA_PROGRAM_ID, ); diff --git a/oracles/pyth/anchor/Anchor.toml b/oracles/pyth/anchor/Anchor.toml index aaead0ef0..6771de0ef 100644 --- a/oracles/pyth/anchor/Anchor.toml +++ b/oracles/pyth/anchor/Anchor.toml @@ -6,10 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -pythexample = "GUkjQmrLPFXXNK1bFLKt8XQi6g3TjxcHVspbjDoHvMG2" - -# [registry] section removed — no longer used in Anchor 1.0 +pythexample = "AWYkDL963P4NXrb9kvik9JTRH7igkhJ4Xyd8t5YRv8ZN" [provider] -cluster = "Localnet" -wallet = "~/.config/solana/id.json" \ No newline at end of file +cluster = "localnet" +wallet = "~/.config/solana/id.json" + +[scripts] +test = "cargo test" + +[hooks] diff --git a/oracles/pyth/anchor/programs/pythexample/Cargo.toml b/oracles/pyth/anchor/programs/pythexample/Cargo.toml index 54cb09608..3d2ed2bfd 100644 --- a/oracles/pyth/anchor/programs/pythexample/Cargo.toml +++ b/oracles/pyth/anchor/programs/pythexample/Cargo.toml @@ -21,9 +21,18 @@ custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" -pyth-solana-receiver-sdk = "1.1.0" +anchor-lang = "1.0.0" +# pyth-solana-receiver-sdk removed: depends on anchor-lang 0.32 which is incompatible +# with Anchor 1.0. PriceUpdateV2 types are inlined in lib.rs. + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-account = "3.0.0" +borsh = "1.6.1" +sha2 = "0.10" +solana-kite = "0.3.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/oracles/pyth/anchor/programs/pythexample/src/lib.rs b/oracles/pyth/anchor/programs/pythexample/src/lib.rs index 8b1e2c56d..fd7f218b9 100644 --- a/oracles/pyth/anchor/programs/pythexample/src/lib.rs +++ b/oracles/pyth/anchor/programs/pythexample/src/lib.rs @@ -1,7 +1,88 @@ -use pyth_solana_receiver_sdk::price_update::PriceUpdateV2; use anchor_lang::prelude::*; -declare_id!("GUkjQmrLPFXXNK1bFLKt8XQi6g3TjxcHVspbjDoHvMG2"); +declare_id!("AWYkDL963P4NXrb9kvik9JTRH7igkhJ4Xyd8t5YRv8ZN"); + +/// Pyth Receiver program ID (rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ) +/// The pyth-solana-receiver-sdk crate depends on anchor-lang 0.32 which is +/// incompatible with Anchor 1.0. These types are inlined to avoid the conflict. +pub const PYTH_RECEIVER_PROGRAM_ID: Pubkey = Pubkey::new_from_array([ + 0x04, 0xdf, 0x5d, 0xa0, 0x26, 0x6c, 0x4f, 0x33, 0x78, 0x18, 0x03, 0xbe, 0x12, 0x90, 0x4e, + 0x07, 0x58, 0x91, 0x53, 0x2a, 0x50, 0x77, 0xb9, 0xba, 0x0f, 0x18, 0x20, 0xe6, 0x2a, 0xb0, + 0x27, 0x49, +]); + +/// Mirrors pyth_solana_receiver_sdk::price_update::VerificationLevel +#[derive(AnchorSerialize, AnchorDeserialize, Copy, Clone, PartialEq, Debug)] +pub enum VerificationLevel { + Partial { num_signatures: u8 }, + Full, +} + +/// Mirrors pythnet_sdk::messages::PriceFeedMessage +#[derive(AnchorSerialize, AnchorDeserialize, Copy, Clone, PartialEq, Debug)] +pub struct PriceFeedMessage { + pub feed_id: [u8; 32], + pub price: i64, + pub conf: u64, + pub exponent: i32, + pub publish_time: i64, + pub prev_publish_time: i64, + pub ema_price: i64, + pub ema_conf: u64, +} + +/// Mirrors pyth_solana_receiver_sdk::price_update::PriceUpdateV2 +/// Re-implemented here because the pyth SDK depends on anchor-lang 0.32.x, +/// which is incompatible with Anchor 1.0's types. +#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug)] +pub struct PriceUpdateV2 { + pub write_authority: Pubkey, + pub verification_level: VerificationLevel, + pub price_message: PriceFeedMessage, + pub posted_slot: u64, +} + +/// Discriminator for PriceUpdateV2 — sha256("account:PriceUpdateV2")[..8] +/// This must match the discriminator used by pyth-solana-receiver-sdk. +pub const PRICE_UPDATE_V2_DISCRIMINATOR: [u8; 8] = { + // Computed at compile time from sha256("account:PriceUpdateV2") + // = [34, 241, 35, 99, 157, 126, 244, 205] + [34, 241, 35, 99, 157, 126, 244, 205] +}; + +impl AccountDeserialize for PriceUpdateV2 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> Result { + // Skip 8-byte discriminator + if buf.len() < 8 { + return Err(ErrorCode::AccountDidNotDeserialize.into()); + } + *buf = &buf[8..]; + AnchorDeserialize::deserialize(buf).map_err(|_| ErrorCode::AccountDidNotDeserialize.into()) + } + + fn try_deserialize(buf: &mut &[u8]) -> Result { + if buf.len() < 8 { + return Err(ErrorCode::AccountDidNotDeserialize.into()); + } + let disc = &buf[..8]; + if disc != PRICE_UPDATE_V2_DISCRIMINATOR { + return Err(ErrorCode::AccountDiscriminatorMismatch.into()); + } + Self::try_deserialize_unchecked(buf) + } +} + +impl AccountSerialize for PriceUpdateV2 {} + +impl Owner for PriceUpdateV2 { + fn owner() -> Pubkey { + PYTH_RECEIVER_PROGRAM_ID + } +} + +impl Discriminator for PriceUpdateV2 { + const DISCRIMINATOR: &'static [u8] = &PRICE_UPDATE_V2_DISCRIMINATOR; +} #[program] pub mod anchor_test { @@ -20,5 +101,6 @@ pub mod anchor_test { #[derive(Accounts)] pub struct ReadPrice<'info> { + /// A PriceUpdateV2 account owned by the Pyth Receiver program. pub price_update: Account<'info, PriceUpdateV2>, } diff --git a/oracles/pyth/anchor/programs/pythexample/tests/test_pyth.rs b/oracles/pyth/anchor/programs/pythexample/tests/test_pyth.rs new file mode 100644 index 000000000..04d545fb9 --- /dev/null +++ b/oracles/pyth/anchor/programs/pythexample/tests/test_pyth.rs @@ -0,0 +1,112 @@ +use { + anchor_lang::{solana_program::instruction::Instruction, InstructionData, ToAccountMetas}, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +/// Pyth Receiver program ID (rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ) +fn pyth_receiver_program_id() -> anchor_lang::solana_program::pubkey::Pubkey { + pythexample::PYTH_RECEIVER_PROGRAM_ID +} + +/// Build mock PriceUpdateV2 account data with Anchor discriminator. +fn build_mock_price_update_account( + write_authority: &anchor_lang::solana_program::pubkey::Pubkey, +) -> Vec { + // Discriminator: sha256("account:PriceUpdateV2")[..8] + let discriminator: [u8; 8] = [34, 241, 35, 99, 157, 126, 244, 205]; + + let mut data = Vec::with_capacity(133); + + // Discriminator + data.extend_from_slice(&discriminator); + + // write_authority: Pubkey (32 bytes) + data.extend_from_slice(write_authority.as_ref()); + + // verification_level: Full = borsh enum variant 1 + data.push(1u8); + + // PriceFeedMessage fields: + // feed_id: [u8; 32] + let feed_id = [0xEFu8; 32]; + data.extend_from_slice(&feed_id); + + // price: i64 (150.00000000 USD with exponent -8) + let price: i64 = 15_000_000_000; + data.extend_from_slice(&price.to_le_bytes()); + + // conf: u64 + let conf: u64 = 100_000; + data.extend_from_slice(&conf.to_le_bytes()); + + // exponent: i32 + let exponent: i32 = -8; + data.extend_from_slice(&exponent.to_le_bytes()); + + // publish_time: i64 + let publish_time: i64 = 1_700_000_000; + data.extend_from_slice(&publish_time.to_le_bytes()); + + // prev_publish_time: i64 + let prev_publish_time: i64 = 1_699_999_999; + data.extend_from_slice(&prev_publish_time.to_le_bytes()); + + // ema_price: i64 + let ema_price: i64 = 14_900_000_000; + data.extend_from_slice(&ema_price.to_le_bytes()); + + // ema_conf: u64 + let ema_conf: u64 = 120_000; + data.extend_from_slice(&ema_conf.to_le_bytes()); + + // posted_slot: u64 + let posted_slot: u64 = 42; + data.extend_from_slice(&posted_slot.to_le_bytes()); + + data +} + +#[test] +fn test_read_price() { + let program_id = pythexample::id(); + let mut svm = LiteSVM::new(); + let bytes = include_bytes!("../../../target/deploy/pythexample.so"); + svm.add_program(program_id, bytes).unwrap(); + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + // Create a mock PriceUpdateV2 account + let price_update_key = Keypair::new(); + let account_data = build_mock_price_update_account(&payer.pubkey()); + + // Set the account in LiteSVM with the Pyth Receiver program as owner + let pyth_receiver_id = pyth_receiver_program_id(); + let rent = svm.minimum_balance_for_rent_exemption(account_data.len()); + + svm.set_account( + price_update_key.pubkey(), + solana_account::Account { + lamports: rent, + data: account_data, + owner: pyth_receiver_id, + executable: false, + rent_epoch: 0, + }, + ) + .unwrap(); + + // Call read_price — program just reads the account and logs the price info + let ix_data = pythexample::instruction::ReadPrice {}.data(); + + let accounts = pythexample::accounts::ReadPrice { + price_update: price_update_key.pubkey(), + } + .to_account_metas(None); + + let instruction = Instruction::new_with_bytes(program_id, &ix_data, accounts); + + send_transaction_from_instructions(&mut svm, vec![instruction], &[&payer], &payer.pubkey()) + .unwrap(); +} diff --git a/package.json b/package.json index 3ed3f9c7f..91b205a0b 100644 --- a/package.json +++ b/package.json @@ -1,37 +1,38 @@ { - "name": "program-examples", - "version": "1.0.0", - "description": "### :crab: Rust. :snake: Python. :link: All onchain.", - "scripts": { - "sync-package-json": "ts-node scripts/sync-package-json.ts", - "format:fix": "pnpx @biomejs/biome format --write ./", - "lint:fix": "pnpx @biomejs/biome lint --write ./", - "lint": "pnpx @biomejs/biome lint ./", - "fix": "pnpx @biomejs/biome check --write ./", - "check": "pnpx @biomejs/biome check ./", - "prepare": "husky" - }, - "lint-staged": { - "*": [ - "biome check --apply --no-errors-on-unmatched --files-ignore-unknown=true" - ] - }, - "keywords": [], - "author": "Solana Foundation", - "license": "MIT", - "devDependencies": { - "@biomejs/biome": "1.8.1", - "@types/node": "^20.9.0", - "husky": "^9.0.11", - "picocolors": "^1.0.0", - "ts-node": "^10.9.1", - "typescript": "^5.2.2" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4", - "anchor-bankrun": "^0.4.0", - "chai": "^5.1.1", - "solana-bankrun": "^0.3.0" - } + "name": "program-examples", + "version": "1.0.0", + "description": "Solana program (smart contract) examples for Anchor, Native Rust, and Pinocchio.", + "scripts": { + "sync-package-json": "ts-node scripts/sync-package-json.ts", + "format:fix": "pnpx @biomejs/biome format --write ./", + "lint:fix": "pnpx @biomejs/biome lint --write ./", + "lint": "pnpx @biomejs/biome lint ./", + "fix": "pnpx @biomejs/biome check --write ./", + "check": "pnpx @biomejs/biome check ./", + "prepare": "husky" + }, + "lint-staged": { + "*": [ + "biome check --write --no-errors-on-unmatched --files-ignore-unknown=true" + ] + }, + "packageManager": "pnpm@9.13.2", + "keywords": [], + "author": "Solana Foundation", + "license": "MIT", + "devDependencies": { + "@biomejs/biome": "2.4.10", + "@types/node": "^20.9.0", + "husky": "^9.0.11", + "picocolors": "^1.0.0", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4", + "anchor-bankrun": "^0.4.0", + "chai": "^5.1.1", + "solana-bankrun": "^0.3.0" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b1f1dc05..1118a53f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10) @@ -25,8 +25,8 @@ importers: version: 0.3.0(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10) devDependencies: '@biomejs/biome': - specifier: 1.8.1 - version: 1.8.1 + specifier: 2.4.10 + version: 2.4.10 '@types/node': specifier: ^20.9.0 version: 20.14.2 @@ -45,77 +45,73 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.25.0': resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==} engines: {node: '>=6.9.0'} - '@biomejs/biome@1.8.1': - resolution: {integrity: sha512-fQXGfvq6DIXem12dGQCM2tNF+vsNHH1qs3C7WeOu75Pd0trduoTmoO7G4ntLJ2qDs5wuw981H+cxQhi1uHnAtA==} + '@biomejs/biome@2.4.10': + resolution: {integrity: sha512-xxA3AphFQ1geij4JTHXv4EeSTda1IFn22ye9LdyVPoJU19fNVl0uzfEuhsfQ4Yue/0FaLs2/ccVi4UDiE7R30w==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@1.8.1': - resolution: {integrity: sha512-XLiB7Uu6GALIOBWzQ2aMD0ru4Ly5/qSeQF7kk3AabzJ/kwsEWSe33iVySBP/SS2qv25cgqNiLksjGcw2bHT3mw==} + '@biomejs/cli-darwin-arm64@2.4.10': + resolution: {integrity: sha512-vuzzI1cWqDVzOMIkYyHbKqp+AkQq4K7k+UCXWpkYcY/HDn1UxdsbsfgtVpa40shem8Kax4TLDLlx8kMAecgqiw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@1.8.1': - resolution: {integrity: sha512-uMTSxVLMfqkBVqyc25hSn83jBbp+wtWjzM/pHFlKXt3htJuw7FErVGW0nmQ9Sxa9vJ7GcqoltLMl28VQRIMYzg==} + '@biomejs/cli-darwin-x64@2.4.10': + resolution: {integrity: sha512-14fzASRo+BPotwp7nWULy2W5xeUyFnTaq1V13Etrrxkrih+ez/2QfgFm5Ehtf5vSjtgx/IJycMMpn5kPd5ZNaA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@1.8.1': - resolution: {integrity: sha512-UQ8Wc01J0wQL+5AYOc7qkJn20B4PZmQL1KrmDZh7ot0DvD6aX4+8mmfd/dG5b6Zjo/44QvCKcvkFGCMRYuhWZA==} + '@biomejs/cli-linux-arm64-musl@2.4.10': + resolution: {integrity: sha512-WrJY6UuiSD/Dh+nwK2qOTu8kdMDlLV3dLMmychIghHPAysWFq1/DGC1pVZx8POE3ZkzKR3PUUnVrtZfMfaJjyQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - libc: [musl] - '@biomejs/cli-linux-arm64@1.8.1': - resolution: {integrity: sha512-3SzZRuC/9Oi2P2IBNPsEj0KXxSXUEYRR2kfRF/Ve8QAfGgrt4qnwuWd6QQKKN5R+oYH691qjm+cXBKEcrP1v/Q==} + '@biomejs/cli-linux-arm64@2.4.10': + resolution: {integrity: sha512-7MH1CMW5uuxQ/s7FLST63qF8B3Hgu2HRdZ7tA1X1+mk+St4JOuIrqdhIBnnyqeyWJNI+Bww7Es5QZ0wIc1Cmkw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - libc: [glibc] - '@biomejs/cli-linux-x64-musl@1.8.1': - resolution: {integrity: sha512-fYbP/kNu/rtZ4kKzWVocIdqZOtBSUEg9qUhZaao3dy3CRzafR6u6KDtBeSCnt47O+iLnks1eOR1TUxzr5+QuqA==} + '@biomejs/cli-linux-x64-musl@2.4.10': + resolution: {integrity: sha512-kDTi3pI6PBN6CiczsWYOyP2zk0IJI08EWEQyDMQWW221rPaaEz6FvjLhnU07KMzLv8q3qSuoB93ua6inSQ55Tw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - libc: [musl] - '@biomejs/cli-linux-x64@1.8.1': - resolution: {integrity: sha512-AeBycVdNrTzsyYKEOtR2R0Ph0hCD0sCshcp2aOnfGP0hCZbtFg09D0SdKLbyzKntisY41HxKVrydYiaApp+2uw==} + '@biomejs/cli-linux-x64@2.4.10': + resolution: {integrity: sha512-tZLvEEi2u9Xu1zAqRjTcpIDGVtldigVvzug2fTuPG0ME/g8/mXpRPcNgLB22bGn6FvLJpHHnqLnwliOu8xjYrg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - libc: [glibc] - '@biomejs/cli-win32-arm64@1.8.1': - resolution: {integrity: sha512-6tEd1H/iFKpgpE3OIB7oNgW5XkjiVMzMRPL8zYoZ036YfuJ5nMYm9eB9H/y81+8Z76vL48fiYzMPotJwukGPqQ==} + '@biomejs/cli-win32-arm64@2.4.10': + resolution: {integrity: sha512-umwQU6qPzH+ISTf/eHyJ/QoQnJs3V9Vpjz2OjZXe9MVBZ7prgGafMy7yYeRGnlmDAn87AKTF3Q6weLoMGpeqdQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@1.8.1': - resolution: {integrity: sha512-g2H31jJzYmS4jkvl6TiyEjEX+Nv79a5km/xn+5DARTp5MBFzC9gwceusSSB2AkJKqZzY131AiACAWjKrVt5Ijw==} + '@biomejs/cli-win32-x64@2.4.10': + resolution: {integrity: sha512-aW/JU5GuyH4uxMrNYpoC2kjaHlyJGLgIa3XkhPEZI0uKhZhJZU8BuEyJmvgzSPQNGozBwWjC972RaNdcJ9KyJg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -430,14 +426,12 @@ packages: engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] solana-bankrun-linux-x64-musl@0.3.0: resolution: {integrity: sha512-xsS2CS2xb1Sw4ivNXM0gPz/qpW9BX0neSvt/pnok5L330Nu9xlTnKAY8FhzzqOP9P9sJlGRM787Y6d0yYwt6xQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] solana-bankrun@0.3.0: resolution: {integrity: sha512-YkH7sa8TB/AoRPzG17CXJtYsRIQHEkEqGLz1Vwc13taXhDBkjO7z6NI5JYw7n0ybRymDHwMYTc7sd+5J40TyVQ==} @@ -534,16 +528,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -561,45 +555,45 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.25.0': dependencies: regenerator-runtime: 0.14.1 - '@biomejs/biome@1.8.1': + '@biomejs/biome@2.4.10': optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.8.1 - '@biomejs/cli-darwin-x64': 1.8.1 - '@biomejs/cli-linux-arm64': 1.8.1 - '@biomejs/cli-linux-arm64-musl': 1.8.1 - '@biomejs/cli-linux-x64': 1.8.1 - '@biomejs/cli-linux-x64-musl': 1.8.1 - '@biomejs/cli-win32-arm64': 1.8.1 - '@biomejs/cli-win32-x64': 1.8.1 - - '@biomejs/cli-darwin-arm64@1.8.1': + '@biomejs/cli-darwin-arm64': 2.4.10 + '@biomejs/cli-darwin-x64': 2.4.10 + '@biomejs/cli-linux-arm64': 2.4.10 + '@biomejs/cli-linux-arm64-musl': 2.4.10 + '@biomejs/cli-linux-x64': 2.4.10 + '@biomejs/cli-linux-x64-musl': 2.4.10 + '@biomejs/cli-win32-arm64': 2.4.10 + '@biomejs/cli-win32-x64': 2.4.10 + + '@biomejs/cli-darwin-arm64@2.4.10': optional: true - '@biomejs/cli-darwin-x64@1.8.1': + '@biomejs/cli-darwin-x64@2.4.10': optional: true - '@biomejs/cli-linux-arm64-musl@1.8.1': + '@biomejs/cli-linux-arm64-musl@2.4.10': optional: true - '@biomejs/cli-linux-arm64@1.8.1': + '@biomejs/cli-linux-arm64@2.4.10': optional: true - '@biomejs/cli-linux-x64-musl@1.8.1': + '@biomejs/cli-linux-x64-musl@2.4.10': optional: true - '@biomejs/cli-linux-x64@1.8.1': + '@biomejs/cli-linux-x64@2.4.10': optional: true - '@biomejs/cli-win32-arm64@1.8.1': + '@biomejs/cli-win32-arm64@2.4.10': optional: true - '@biomejs/cli-win32-x64@1.8.1': + '@biomejs/cli-win32-x64@2.4.10': optional: true '@coral-xyz/anchor-errors@0.31.1': {} diff --git a/scripts/lib/change-package-version.ts b/scripts/lib/change-package-version.ts index 0e8dab176..ee32d7c61 100644 --- a/scripts/lib/change-package-version.ts +++ b/scripts/lib/change-package-version.ts @@ -1,7 +1,7 @@ -import { readFileSync } from 'node:fs'; +import { readFileSync } from "node:fs"; export function changePackageVersion(file: string, pkgName: string, pkgVersion: string): [boolean, string] { - const content = JSON.parse(readFileSync(file).toString('utf-8')); + const content = JSON.parse(readFileSync(file).toString("utf-8")); if (content.dependencies?.[pkgName] && content.dependencies[pkgName] !== pkgVersion) { content.dependencies[pkgName] = pkgVersion; return [true, content]; diff --git a/scripts/lib/command-check.ts b/scripts/lib/command-check.ts index 99c3d5bb8..7d13f50dc 100644 --- a/scripts/lib/command-check.ts +++ b/scripts/lib/command-check.ts @@ -1,10 +1,10 @@ -import { basename } from 'node:path'; -import * as p from 'picocolors'; -import { getDepsCount } from './get-deps-count'; -import { getRecursiveFileList } from './get-recursive-file-list'; +import { basename } from "node:path"; +import * as p from "picocolors"; +import { getDepsCount } from "./get-deps-count"; +import { getRecursiveFileList } from "./get-recursive-file-list"; -export function commandCheck(path = '.') { - const files = getRecursiveFileList(path).filter((file) => basename(file) === 'package.json'); +export function commandCheck(path = ".") { + const files = getRecursiveFileList(path).filter((file) => basename(file) === "package.json"); const depsCounter = getDepsCount(files); const single: string[] = []; @@ -17,7 +17,7 @@ export function commandCheck(path = '.') { if (versionsLength === 1) { const count = versions[versionMap[0]].length; - single.push(`${p.green('✔')} ${pkg}@${versionMap[0]} (${count})`); + single.push(`${p.green("✔")} ${pkg}@${versionMap[0]} (${count})`); continue; } @@ -27,7 +27,7 @@ export function commandCheck(path = '.') { } versionCount.sort((a, b) => b.count - a.count); - multiple.push(`${p.yellow('⚠')} ${pkg} has ${versionsLength} versions:`); + multiple.push(`${p.yellow("⚠")} ${pkg} has ${versionsLength} versions:`); for (const { count, version } of versionCount) { multiple.push(` - ${p.bold(version)} (${count})`); diff --git a/scripts/lib/command-help.ts b/scripts/lib/command-help.ts index dfbe8021f..6fe22dd5c 100644 --- a/scripts/lib/command-help.ts +++ b/scripts/lib/command-help.ts @@ -1,26 +1,26 @@ export function commandHelp() { - console.log('Usage: yarn sync-package-json [options]'); - console.log(''); - console.log('Commands:'); - console.log(' check Check package.json files'); - console.log(' help Show this help'); - console.log(' list List package.json files'); - console.log(' set [ver] Set specific version in package.json files'); - console.log(' update Update all versions in package.json files'); - console.log(''); - console.log('Arguments:'); - console.log(' path Path to directory'); - console.log(''); - console.log('Examples:'); - console.log(' yarn sync-package-json check'); - console.log(' yarn sync-package-json check basics'); - console.log(' yarn sync-package-json list'); - console.log(' yarn sync-package-json list basics'); - console.log(' yarn sync-package-json help'); - console.log(' yarn sync-package-json set @coral-xyz/anchor@0.29.0'); - console.log(' yarn sync-package-json set @coral-xyz/anchor@0.29.0 basics'); - console.log(' yarn sync-package-json update'); - console.log(' yarn sync-package-json update basics'); - console.log(' yarn sync-package-json update . @solana/web3.js @solana/spl-token'); + console.log("Usage: yarn sync-package-json [options]"); + console.log(""); + console.log("Commands:"); + console.log(" check Check package.json files"); + console.log(" help Show this help"); + console.log(" list List package.json files"); + console.log(" set [ver] Set specific version in package.json files"); + console.log(" update Update all versions in package.json files"); + console.log(""); + console.log("Arguments:"); + console.log(" path Path to directory"); + console.log(""); + console.log("Examples:"); + console.log(" yarn sync-package-json check"); + console.log(" yarn sync-package-json check basics"); + console.log(" yarn sync-package-json list"); + console.log(" yarn sync-package-json list basics"); + console.log(" yarn sync-package-json help"); + console.log(" yarn sync-package-json set @coral-xyz/anchor@0.29.0"); + console.log(" yarn sync-package-json set @coral-xyz/anchor@0.29.0 basics"); + console.log(" yarn sync-package-json update"); + console.log(" yarn sync-package-json update basics"); + console.log(" yarn sync-package-json update . @solana/web3.js @solana/spl-token"); process.exit(0); } diff --git a/scripts/lib/command-list.ts b/scripts/lib/command-list.ts index a127c1a73..fdda272aa 100644 --- a/scripts/lib/command-list.ts +++ b/scripts/lib/command-list.ts @@ -1,8 +1,8 @@ -import { basename } from 'node:path'; -import { getRecursiveFileList } from './get-recursive-file-list'; +import { basename } from "node:path"; +import { getRecursiveFileList } from "./get-recursive-file-list"; export function commandList(path: string) { - const files = getRecursiveFileList(path).filter((file) => basename(file) === 'package.json'); + const files = getRecursiveFileList(path).filter((file) => basename(file) === "package.json"); for (const file of files) { console.log(file); } diff --git a/scripts/lib/command-set.ts b/scripts/lib/command-set.ts index 33d5be755..cad1dc6c0 100644 --- a/scripts/lib/command-set.ts +++ b/scripts/lib/command-set.ts @@ -1,32 +1,32 @@ -import { writeFileSync } from 'node:fs'; -import { basename } from 'node:path'; -import { changePackageVersion } from './change-package-version'; -import { getRecursiveFileList } from './get-recursive-file-list'; +import { writeFileSync } from "node:fs"; +import { basename } from "node:path"; +import { changePackageVersion } from "./change-package-version"; +import { getRecursiveFileList } from "./get-recursive-file-list"; -export function commandSet(version: string, path = '.') { +export function commandSet(version: string, path = ".") { if (!version) { - console.error('Version is required'); + console.error("Version is required"); process.exit(1); } if ( !version // Strip first character if it's a `@` - .replace(/^@/, '') - .includes('@') + .replace(/^@/, "") + .includes("@") ) { console.error(`Invalid package version: ${version}. Provide package with version, e.g. @solana/web3.js@1.0.0`); process.exit(1); } // Take anything after the second `@` as the version, the rest is the package name - const [pkg, ...rest] = version.split('@').reverse(); - const pkgName = rest.reverse().join('@'); + const [pkg, ...rest] = version.split("@").reverse(); + const pkgName = rest.reverse().join("@"); // Make sure pkgVersions has a ^ prefix, if not add it - const pkgVersion = pkg.startsWith('^') ? pkg : `^${pkg}`; + const pkgVersion = pkg.startsWith("^") ? pkg : `^${pkg}`; console.log(`Setting package ${pkgName} to ${pkgVersion} in ${path}`); - const files = getRecursiveFileList(path).filter((file) => basename(file) === 'package.json'); + const files = getRecursiveFileList(path).filter((file) => basename(file) === "package.json"); let count = 0; for (const file of files) { const [changed, content] = changePackageVersion(file, pkgName, pkgVersion); @@ -36,7 +36,7 @@ export function commandSet(version: string, path = '.') { } } if (count === 0) { - console.log('No files updated'); + console.log("No files updated"); } else { console.log(`Updated ${count} files`); } diff --git a/scripts/lib/command-update.ts b/scripts/lib/command-update.ts index 360d75dd9..02c724a78 100644 --- a/scripts/lib/command-update.ts +++ b/scripts/lib/command-update.ts @@ -1,18 +1,18 @@ -import { execSync } from 'node:child_process'; -import { writeFileSync } from 'node:fs'; -import { basename } from 'node:path'; -import * as p from 'picocolors'; -import { changePackageVersion } from './change-package-version'; +import { execSync } from "node:child_process"; +import { writeFileSync } from "node:fs"; +import { basename } from "node:path"; +import * as p from "picocolors"; +import { changePackageVersion } from "./change-package-version"; -import { getDepsCount } from './get-deps-count'; -import { getRecursiveFileList } from './get-recursive-file-list'; +import { getDepsCount } from "./get-deps-count"; +import { getRecursiveFileList } from "./get-recursive-file-list"; -export function commandUpdate(path = '.', packageNames: string[] = []) { - const files = getRecursiveFileList(path).filter((file) => basename(file) === 'package.json'); +export function commandUpdate(path = ".", packageNames: string[] = []) { + const files = getRecursiveFileList(path).filter((file) => basename(file) === "package.json"); const depsCounter = getDepsCount(files); const pkgNames = Object.keys(depsCounter).sort(); if (packageNames.length > 0) { - console.log(`Updating ${packageNames.join(', ')} in ${files.length} files`); + console.log(`Updating ${packageNames.join(", ")} in ${files.length} files`); } let total = 0; @@ -38,7 +38,7 @@ export function commandUpdate(path = '.', packageNames: string[] = []) { } if (total === 0) { - console.log('No files updated'); + console.log("No files updated"); } else { console.log(`Updated ${total} files`); } diff --git a/scripts/lib/get-deps-count.ts b/scripts/lib/get-deps-count.ts index 4481213a1..087bed171 100644 --- a/scripts/lib/get-deps-count.ts +++ b/scripts/lib/get-deps-count.ts @@ -1,11 +1,11 @@ -import { readFileSync } from 'node:fs'; +import { readFileSync } from "node:fs"; export function getDepsCount(files: string[] = []): Record> { const map: Record = {}; const depsCounter: Record> = {}; for (const file of files) { - const content = JSON.parse(readFileSync(file).toString('utf-8')); + const content = JSON.parse(readFileSync(file).toString("utf-8")); map[file] = content; const deps = content.dependencies ?? {}; diff --git a/scripts/lib/get-recursive-file-list.ts b/scripts/lib/get-recursive-file-list.ts index 8c65fbea1..951df23e5 100644 --- a/scripts/lib/get-recursive-file-list.ts +++ b/scripts/lib/get-recursive-file-list.ts @@ -1,8 +1,8 @@ // Point method at path and return a list of all the files in the directory recursively -import { readdirSync, statSync } from 'node:fs'; +import { readdirSync, statSync } from "node:fs"; export function getRecursiveFileList(path: string): string[] { - const ignore = ['.git', '.github', '.idea', '.next', '.vercel', '.vscode', 'coverage', 'dist', 'node_modules']; + const ignore = [".git", ".github", ".idea", ".next", ".vercel", ".vscode", "coverage", "dist", "node_modules"]; const files: string[] = []; const items = readdirSync(path); @@ -23,6 +23,6 @@ export function getRecursiveFileList(path: string): string[] { return files.filter((file) => { // Remove package.json from the root directory - return path === '.' ? file !== './package.json' : true; + return path === "." ? file !== "./package.json" : true; }); } diff --git a/scripts/lib/index.ts b/scripts/lib/index.ts index 37dfbc8cf..0d9c97099 100644 --- a/scripts/lib/index.ts +++ b/scripts/lib/index.ts @@ -1,5 +1,5 @@ -export * from './command-check'; -export * from './command-help'; -export * from './command-list'; -export * from './command-set'; -export * from './command-update'; +export * from "./command-check"; +export * from "./command-help"; +export * from "./command-list"; +export * from "./command-set"; +export * from "./command-update"; diff --git a/scripts/sync-package-json.ts b/scripts/sync-package-json.ts index 1ecec29bd..56844c92e 100644 --- a/scripts/sync-package-json.ts +++ b/scripts/sync-package-json.ts @@ -1,18 +1,18 @@ -import { commandCheck, commandHelp, commandList, commandSet, commandUpdate } from './lib'; +import { commandCheck, commandHelp, commandList, commandSet, commandUpdate } from "./lib"; const params: string[] = process.argv.slice(3); switch (process.argv[2]) { - case 'check': + case "check": commandCheck(params[0]); break; - case 'list': + case "list": commandList(params[0]); break; - case 'set': + case "set": commandSet(params[0], params[1]); break; - case 'update': + case "update": commandUpdate(params[0], params.slice(1)); break; default: diff --git a/tokens/create-token/anchor/Anchor.toml b/tokens/create-token/anchor/Anchor.toml index 5ea5f5207..3a7c0d739 100644 --- a/tokens/create-token/anchor/Anchor.toml +++ b/tokens/create-token/anchor/Anchor.toml @@ -6,16 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -create_token = "GwvQ53QTu1xz3XXYfG5m5jEqwhMBvVBudPS8TUuFYnhT" - -# [registry] section removed — no longer used in Anchor 1.0 +create_token = "Ex6CEJiwPiCotaNYmrjLSKQTr27tXrrA7981XZuQHQWe" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -# Only run bankrun tests — the validator tests (test.ts) need Metaplex Token -# Metadata cloned from mainnet which is too slow/unreliable in CI. -# bankrun.test.ts uses a local fixture (tests/fixtures/token_metadata.so). -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/bankrun.test.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/create-token/anchor/package.json b/tokens/create-token/anchor/package.json index 9dec90fba..ef819b42b 100644 --- a/tokens/create-token/anchor/package.json +++ b/tokens/create-token/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5" - }, - "scripts": { - "postinstall": "zx prepare.mjs" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3", - "zx": "^8.1.4" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0" + }, + "scripts": { + "postinstall": "zx prepare.mjs" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3", + "zx": "^8.1.4" + } } diff --git a/tokens/create-token/anchor/pnpm-lock.yaml b/tokens/create-token/anchor/pnpm-lock.yaml index 2562c11f2..ffe6cb8cb 100644 --- a/tokens/create-token/anchor/pnpm-lock.yaml +++ b/tokens/create-token/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) devDependencies: '@types/bn.js': specifier: ^5.1.0 @@ -45,18 +45,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -764,16 +764,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -791,7 +791,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/create-token/anchor/prepare.mjs b/tokens/create-token/anchor/prepare.mjs index 7c5ec464b..fb6b26225 100644 --- a/tokens/create-token/anchor/prepare.mjs +++ b/tokens/create-token/anchor/prepare.mjs @@ -1,17 +1,17 @@ #!/usr/bin/env zx -import { mkdir, rm } from 'node:fs/promises'; -import { join } from 'node:path'; -import { $ } from 'zx'; +import { mkdir, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { $ } from "zx"; const programs = [ { - id: 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', - name: 'token_metadata.so', + id: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", + name: "token_metadata.so", }, ]; -const outputDir = 'tests/fixtures'; +const outputDir = "tests/fixtures"; const overwrite = true; try { diff --git a/tokens/create-token/anchor/programs/create-token/Cargo.toml b/tokens/create-token/anchor/programs/create-token/Cargo.toml index 88ec78c89..f0fbf0421 100644 --- a/tokens/create-token/anchor/programs/create-token/Cargo.toml +++ b/tokens/create-token/anchor/programs/create-token/Cargo.toml @@ -21,9 +21,15 @@ custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" -anchor-spl = { version = "1.0.0-rc.5", features = ["metadata"] } +anchor-lang = "1.0.0" +anchor-spl = { version = "1.0.0", features = ["metadata"] } + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/create-token/anchor/programs/create-token/src/lib.rs b/tokens/create-token/anchor/programs/create-token/src/lib.rs index 599dfd9d6..c0117de76 100644 --- a/tokens/create-token/anchor/programs/create-token/src/lib.rs +++ b/tokens/create-token/anchor/programs/create-token/src/lib.rs @@ -9,7 +9,7 @@ use { }, }; -declare_id!("GwvQ53QTu1xz3XXYfG5m5jEqwhMBvVBudPS8TUuFYnhT"); +declare_id!("Ex6CEJiwPiCotaNYmrjLSKQTr27tXrrA7981XZuQHQWe"); #[program] pub mod create_token { diff --git a/tokens/create-token/anchor/programs/create-token/tests/test_create_token.rs b/tokens/create-token/anchor/programs/create-token/tests/test_create_token.rs new file mode 100644 index 000000000..8acc0195d --- /dev/null +++ b/tokens/create-token/anchor/programs/create-token/tests/test_create_token.rs @@ -0,0 +1,145 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +fn metadata_program_id() -> Pubkey { + "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + .parse() + .unwrap() +} + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn rent_sysvar_id() -> Pubkey { + "SysvarRent111111111111111111111111111111111" + .parse() + .unwrap() +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = create_token::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/create_token.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let metadata_bytes = include_bytes!("../../../tests/fixtures/mpl_token_metadata.so"); + svm.add_program(metadata_program_id(), metadata_bytes) + .unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +fn derive_metadata_pda(mint: &Pubkey) -> Pubkey { + let metadata_pid = metadata_program_id(); + let (pda, _bump) = Pubkey::find_program_address( + &[b"metadata", metadata_pid.as_ref(), mint.as_ref()], + &metadata_pid, + ); + pda +} + +#[test] +fn test_create_spl_token() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + let metadata_account = derive_metadata_pda(&mint_keypair.pubkey()); + + let instruction = Instruction::new_with_bytes( + program_id, + &create_token::instruction::CreateTokenMint { + _token_decimals: 9, + token_name: "Solana Gold".to_string(), + token_symbol: "GOLDSOL".to_string(), + token_uri: "https://example.com/token.json".to_string(), + } + .data(), + create_token::accounts::CreateTokenMint { + payer: payer.pubkey(), + metadata_account, + mint_account: mint_keypair.pubkey(), + token_metadata_program: metadata_program_id(), + token_program: token_program_id(), + system_program: system_program::id(), + rent: rent_sysvar_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &mint_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Verify the mint account exists + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should exist"); + assert!(!mint_account.data.is_empty(), "Mint account should have data"); + + // Verify the metadata account was created + let meta_account = svm + .get_account(&metadata_account) + .expect("Metadata account should exist"); + assert!( + !meta_account.data.is_empty(), + "Metadata account should have data" + ); +} + +#[test] +fn test_create_nft() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + let metadata_account = derive_metadata_pda(&mint_keypair.pubkey()); + + let instruction = Instruction::new_with_bytes( + program_id, + &create_token::instruction::CreateTokenMint { + _token_decimals: 0, + token_name: "Solana Gold".to_string(), + token_symbol: "GOLDSOL".to_string(), + token_uri: "https://example.com/nft.json".to_string(), + } + .data(), + create_token::accounts::CreateTokenMint { + payer: payer.pubkey(), + metadata_account, + mint_account: mint_keypair.pubkey(), + token_metadata_program: metadata_program_id(), + token_program: token_program_id(), + system_program: system_program::id(), + rent: rent_sysvar_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &mint_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Verify the mint account exists + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should exist"); + assert!(!mint_account.data.is_empty(), "Mint account should have data"); +} diff --git a/tokens/create-token/anchor/tests/bankrun.test.ts b/tokens/create-token/anchor/tests/bankrun.test.ts index e2ce027f3..37a0ab291 100644 --- a/tokens/create-token/anchor/tests/bankrun.test.ts +++ b/tokens/create-token/anchor/tests/bankrun.test.ts @@ -8,9 +8,7 @@ import type { CreateToken } from "../target/types/create_token"; // requires TypeScript 5.3+, but this project uses typescript ^4.3.5 with ts-mocha. const IDL = require("../target/idl/create_token.json"); const PROGRAM_ID = new PublicKey(IDL.address); -const METADATA_PROGRAM_ID = new PublicKey( - "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", -); +const METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); describe("Bankrun example", async () => { const context = await startAnchor( diff --git a/tokens/create-token/anchor/tests/fixtures/mpl_token_metadata.so b/tokens/create-token/anchor/tests/fixtures/mpl_token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/create-token/anchor/tests/fixtures/mpl_token_metadata.so differ diff --git a/tokens/create-token/anchor/tests/fixtures/token_metadata.so b/tokens/create-token/anchor/tests/fixtures/token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/create-token/anchor/tests/fixtures/token_metadata.so differ diff --git a/tokens/create-token/anchor/tests/test.ts b/tokens/create-token/anchor/tests/test.ts index 4f673627b..cafce25ee 100644 --- a/tokens/create-token/anchor/tests/test.ts +++ b/tokens/create-token/anchor/tests/test.ts @@ -1,20 +1,20 @@ -import * as anchor from '@anchor-lang/core'; -import { Keypair } from '@solana/web3.js'; -import type { CreateToken } from '../target/types/create_token'; +import * as anchor from "@anchor-lang/core"; +import { Keypair } from "@solana/web3.js"; +import type { CreateToken } from "../target/types/create_token"; -describe('Create Tokens', () => { +describe("Create Tokens", () => { const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); const payer = provider.wallet as anchor.Wallet; const program = anchor.workspace.CreateToken as anchor.Program; const metadata = { - name: 'Solana Gold', - symbol: 'GOLDSOL', - uri: 'https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json', + name: "Solana Gold", + symbol: "GOLDSOL", + uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", }; - it('Create an SPL Token!', async () => { + it("Create an SPL Token!", async () => { // Generate new keypair to use as address for mint account. const mintKeypair = new Keypair(); @@ -28,12 +28,12 @@ describe('Create Tokens', () => { .signers([mintKeypair]) .rpc(); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${mintKeypair.publicKey}`); console.log(` Transaction Signature: ${transactionSignature}`); }); - it('Create an NFT!', async () => { + it("Create an NFT!", async () => { // Generate new keypair to use as address for mint account. const mintKeypair = new Keypair(); @@ -47,7 +47,7 @@ describe('Create Tokens', () => { .signers([mintKeypair]) .rpc(); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${mintKeypair.publicKey}`); console.log(` Transaction Signature: ${transactionSignature}`); }); diff --git a/tokens/create-token/native/package.json b/tokens/create-token/native/package.json index 88dcb0d51..192560abc 100644 --- a/tokens/create-token/native/package.json +++ b/tokens/create-token/native/package.json @@ -1,26 +1,26 @@ { - "scripts": { - "test": "pnpm ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts", - "build-and-test": "cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./tests/fixtures && pnpm test", - "build": "cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./program/target/so", - "deploy": "solana program deploy ./program/target/so/hello_solana_program.so" - }, - "dependencies": { - "@metaplex-foundation/mpl-token-metadata": "^2.5.2", - "@solana/spl-token": "^0.3.7", - "@solana/web3.js": "^1.98.4", - "borsh": "^2.0.0", - "buffer": "^6.0.3", - "fs": "^0.0.1-security" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.1", - "@types/mocha": "^9.1.1", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", - "typescript": "^5" - }, - "type": "module" + "scripts": { + "test": "pnpm ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts", + "build-and-test": "cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./tests/fixtures && pnpm test", + "build": "cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./program/target/so", + "deploy": "solana program deploy ./program/target/so/hello_solana_program.so" + }, + "dependencies": { + "@metaplex-foundation/mpl-token-metadata": "^2.5.2", + "@solana/spl-token": "^0.3.7", + "@solana/web3.js": "^1.98.4", + "borsh": "^2.0.0", + "buffer": "^6.0.3", + "fs": "^0.0.1-security" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.1", + "@types/mocha": "^9.1.1", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "ts-mocha": "^10.0.0", + "typescript": "^5" + }, + "type": "module" } diff --git a/tokens/create-token/native/tests/test.ts b/tokens/create-token/native/tests/test.ts index d583c7798..69a530d2a 100644 --- a/tokens/create-token/native/tests/test.ts +++ b/tokens/create-token/native/tests/test.ts @@ -1,6 +1,6 @@ -import { Buffer } from 'node:buffer'; -import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from '@metaplex-foundation/mpl-token-metadata'; -import { TOKEN_PROGRAM_ID } from '@solana/spl-token'; +import { Buffer } from "node:buffer"; +import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata"; +import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; import { Connection, Keypair, @@ -10,19 +10,19 @@ import { sendAndConfirmTransaction, Transaction, TransactionInstruction, -} from '@solana/web3.js'; -import * as borsh from 'borsh'; +} from "@solana/web3.js"; +import * as borsh from "borsh"; function createKeypairFromFile(path: string): Keypair { - return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require('node:fs').readFileSync(path, 'utf-8')))); + return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require("node:fs").readFileSync(path, "utf-8")))); } const CreateTokenArgsSchema = { struct: { - token_title: 'string', - token_symbol: 'string', - token_uri: 'string', - token_decimals: 'u8', + token_title: "string", + token_symbol: "string", + token_uri: "string", + token_decimals: "u8", }, }; @@ -30,26 +30,27 @@ function borshSerialize(schema: borsh.Schema, data: object): Buffer { return Buffer.from(borsh.serialize(schema, data)); } -describe('Create Tokens!', async () => { +describe("Create Tokens!", async () => { // const connection = new Connection(`http://localhost:8899`, 'confirmed'); - const connection = new Connection('https://api.devnet.solana.com/', 'confirmed'); - const payer = createKeypairFromFile(`${require('node:os').homedir()}/.config/solana/id.json`); - const program = createKeypairFromFile('./program/target/deploy/program-keypair.json'); + const connection = new Connection("https://api.devnet.solana.com/", "confirmed"); + const payer = createKeypairFromFile(`${require("node:os").homedir()}/.config/solana/id.json`); + const program = createKeypairFromFile("./program/target/deploy/program-keypair.json"); - it('Create an SPL Token!', async () => { + it("Create an SPL Token!", async () => { const mintKeypair: Keypair = Keypair.generate(); const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; // SPL Token default = 9 decimals // const instructionData = borshSerialize(CreateTokenArgsSchema, { - token_title: 'Solana Gold', - token_symbol: 'GOLDSOL', - token_uri: 'https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json', + token_title: "Solana Gold", + token_symbol: "GOLDSOL", + token_uri: + "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", token_decimals: 9, }); @@ -74,25 +75,26 @@ describe('Create Tokens!', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, mintKeypair]); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${mintKeypair.publicKey}`); console.log(` Tx Signature: ${sx}`); }); - it('Create an NFT!', async () => { + it("Create an NFT!", async () => { const mintKeypair: Keypair = Keypair.generate(); const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; // NFT default = 0 decimals // const instructionData = borshSerialize(CreateTokenArgsSchema, { - token_title: 'Homer NFT', - token_symbol: 'HOMR', - token_uri: 'https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json', + token_title: "Homer NFT", + token_symbol: "HOMR", + token_uri: + "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json", token_decimals: 9, }); @@ -117,7 +119,7 @@ describe('Create Tokens!', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, mintKeypair]); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${mintKeypair.publicKey}`); console.log(` Tx Signature: ${sx}`); }); diff --git a/tokens/escrow/anchor/Anchor.toml b/tokens/escrow/anchor/Anchor.toml index 95d4c4342..07b29cef7 100644 --- a/tokens/escrow/anchor/Anchor.toml +++ b/tokens/escrow/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -escrow = "qbuMdeYxYJXBjU6C6qFKjZKjXmrU83eDQomHdrch826" - -# [registry] section removed — no longer used in Anchor 1.0 +escrow = "4uNGr59nikomHqBMi8ckLBiuBQu6eSTRsCvcSoygXhLK" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.test.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/escrow/anchor/migrations/deploy.ts b/tokens/escrow/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/escrow/anchor/migrations/deploy.ts +++ b/tokens/escrow/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/escrow/anchor/package.json b/tokens/escrow/anchor/package.json index 06fd044a4..29b7034ed 100644 --- a/tokens/escrow/anchor/package.json +++ b/tokens/escrow/anchor/package.json @@ -1,27 +1,27 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana-developers/helpers": "^2.8.1", - "@solana/spl-token": "^0.4.14", - "@solana/web3.js": "^1.98.4" - }, - "license": "MIT", - "devDependencies": { - "@types/bn.js": "^5.2.0", - "@types/chai": "^5.2.3", - "@types/mocha": "^10.0.10", - "anchor-bankrun": "^0.5.0", - "chai": "^6.2.2", - "mocha": "^11.7.5", - "prettier": "^3.7.4", - "solana-bankrun": "^0.4.0", - "ts-mocha": "^11.1.0", - "ts-node": "^10.9.2", - "typescript": "^5.9.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana-developers/helpers": "^2.8.1", + "@solana/spl-token": "^0.4.14", + "@solana/web3.js": "^1.98.4" + }, + "license": "MIT", + "devDependencies": { + "@types/bn.js": "^5.2.0", + "@types/chai": "^5.2.3", + "@types/mocha": "^10.0.10", + "anchor-bankrun": "^0.5.0", + "chai": "^6.2.2", + "mocha": "^11.7.5", + "prettier": "^3.7.4", + "solana-bankrun": "^0.4.0", + "ts-mocha": "^11.1.0", + "ts-node": "^10.9.2", + "typescript": "^5.9.3" + } } diff --git a/tokens/escrow/anchor/pnpm-lock.yaml b/tokens/escrow/anchor/pnpm-lock.yaml index 52b251d71..e855bc5b6 100644 --- a/tokens/escrow/anchor/pnpm-lock.yaml +++ b/tokens/escrow/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana-developers/helpers': specifier: ^2.8.1 version: 2.8.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -57,18 +57,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -890,16 +890,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -917,7 +917,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/escrow/anchor/programs/escrow/Cargo.toml b/tokens/escrow/anchor/programs/escrow/Cargo.toml index 5cab9dff0..7ae25149d 100644 --- a/tokens/escrow/anchor/programs/escrow/Cargo.toml +++ b/tokens/escrow/anchor/programs/escrow/Cargo.toml @@ -20,9 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"]} -anchor-spl = "1.0.0-rc.5" +anchor-lang = { version = "1.0.0", features = ["init-if-needed"]} +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/escrow/anchor/programs/escrow/src/lib.rs b/tokens/escrow/anchor/programs/escrow/src/lib.rs index 686b770d6..a49633cec 100644 --- a/tokens/escrow/anchor/programs/escrow/src/lib.rs +++ b/tokens/escrow/anchor/programs/escrow/src/lib.rs @@ -9,7 +9,7 @@ pub use constants::*; pub use instructions::*; pub use state::*; -declare_id!("qbuMdeYxYJXBjU6C6qFKjZKjXmrU83eDQomHdrch826"); +declare_id!("4uNGr59nikomHqBMi8ckLBiuBQu6eSTRsCvcSoygXhLK"); #[program] pub mod escrow { diff --git a/tokens/escrow/anchor/programs/escrow/tests/test_escrow.rs b/tokens/escrow/anchor/programs/escrow/tests/test_escrow.rs new file mode 100644 index 000000000..3d97ccbac --- /dev/null +++ b/tokens/escrow/anchor/programs/escrow/tests/test_escrow.rs @@ -0,0 +1,279 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{ + create_associated_token_account, create_token_mint, create_wallet, + get_token_account_balance, mint_tokens_to_token_account, send_transaction_from_instructions, + }, + solana_signer::Signer, +}; + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn ata_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn derive_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey { + let (ata, _bump) = Pubkey::find_program_address( + &[wallet.as_ref(), token_program_id().as_ref(), mint.as_ref()], + &ata_program_id(), + ); + ata +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = escrow::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/escrow.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 100_000_000_000).unwrap(); + (svm, program_id, payer) +} + +struct EscrowSetup { + svm: LiteSVM, + program_id: Pubkey, + payer: Keypair, + alice: Keypair, + bob: Keypair, + mint_a: Pubkey, + mint_b: Pubkey, + alice_ata_a: Pubkey, + alice_ata_b: Pubkey, + bob_ata_a: Pubkey, + bob_ata_b: Pubkey, +} + +fn full_setup() -> EscrowSetup { + let (mut svm, program_id, payer) = setup(); + + let alice = create_wallet(&mut svm, 10_000_000_000).unwrap(); + let bob = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + let decimals: u8 = 6; + let alice_amount: u64 = 1_000_000_000; + let bob_amount: u64 = 1_000_000_000; + + // Create mints (payer is mint authority) + let mint_a = create_token_mint(&mut svm, &payer, decimals, None).unwrap(); + let mint_b = create_token_mint(&mut svm, &payer, decimals, None).unwrap(); + + // Create ATAs + let alice_ata_a = + create_associated_token_account(&mut svm, &alice.pubkey(), &mint_a, &payer).unwrap(); + let alice_ata_b = + create_associated_token_account(&mut svm, &alice.pubkey(), &mint_b, &payer).unwrap(); + let bob_ata_b = + create_associated_token_account(&mut svm, &bob.pubkey(), &mint_b, &payer).unwrap(); + + // bob_ata_a is derived but not pre-created (program uses init_if_needed) + let bob_ata_a = derive_ata(&bob.pubkey(), &mint_a); + + // Mint tokens: Alice gets token A, Bob gets token B + mint_tokens_to_token_account(&mut svm, &mint_a, &alice_ata_a, alice_amount, &payer).unwrap(); + mint_tokens_to_token_account(&mut svm, &mint_b, &bob_ata_b, bob_amount, &payer).unwrap(); + + EscrowSetup { + svm, + program_id, + payer, + alice, + bob, + mint_a, + mint_b, + alice_ata_a, + alice_ata_b, + bob_ata_a, + bob_ata_b, + } +} + +#[test] +fn test_make_offer() { + let mut es = full_setup(); + + let offer_id: u64 = 1; + let token_a_offered_amount: u64 = 1_000_000; + let token_b_wanted_amount: u64 = 1_000_000; + + // Derive offer PDA + let (offer_pda, _bump) = Pubkey::find_program_address( + &[ + b"offer", + es.alice.pubkey().as_ref(), + &offer_id.to_le_bytes(), + ], + &es.program_id, + ); + + // Vault is the ATA of the offer PDA for mint_a + let vault = derive_ata(&offer_pda, &es.mint_a); + + let make_offer_ix = Instruction::new_with_bytes( + es.program_id, + &escrow::instruction::MakeOffer { + id: offer_id, + token_a_offered_amount, + token_b_wanted_amount, + } + .data(), + escrow::accounts::MakeOffer { + maker: es.alice.pubkey(), + token_mint_a: es.mint_a, + token_mint_b: es.mint_b, + maker_token_account_a: es.alice_ata_a, + offer: offer_pda, + vault, + associated_token_program: ata_program_id(), + token_program: token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut es.svm, + vec![make_offer_ix], + &[&es.payer, &es.alice], + &es.payer.pubkey(), + ) + .unwrap(); + + // Verify vault contains the offered tokens + assert_eq!( + get_token_account_balance(&es.svm, &vault).unwrap(), + token_a_offered_amount + ); + + // Verify offer account data + let offer_data = es.svm.get_account(&offer_pda).expect("Offer should exist"); + let data = &offer_data.data[8..]; // Skip 8-byte discriminator + let stored_id = u64::from_le_bytes(data[0..8].try_into().unwrap()); + assert_eq!(stored_id, offer_id); + let stored_maker = Pubkey::try_from(&data[8..40]).unwrap(); + assert_eq!(stored_maker, es.alice.pubkey()); +} + +#[test] +fn test_take_offer() { + let mut es = full_setup(); + + let offer_id: u64 = 2; + let token_a_offered_amount: u64 = 1_000_000; + let token_b_wanted_amount: u64 = 1_000_000; + + // Derive offer PDA + let (offer_pda, _bump) = Pubkey::find_program_address( + &[ + b"offer", + es.alice.pubkey().as_ref(), + &offer_id.to_le_bytes(), + ], + &es.program_id, + ); + + let vault = derive_ata(&offer_pda, &es.mint_a); + + // Step 1: Alice makes the offer + let make_offer_ix = Instruction::new_with_bytes( + es.program_id, + &escrow::instruction::MakeOffer { + id: offer_id, + token_a_offered_amount, + token_b_wanted_amount, + } + .data(), + escrow::accounts::MakeOffer { + maker: es.alice.pubkey(), + token_mint_a: es.mint_a, + token_mint_b: es.mint_b, + maker_token_account_a: es.alice_ata_a, + offer: offer_pda, + vault, + associated_token_program: ata_program_id(), + token_program: token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut es.svm, + vec![make_offer_ix], + &[&es.payer, &es.alice], + &es.payer.pubkey(), + ) + .unwrap(); + + // Verify vault has tokens + assert_eq!( + get_token_account_balance(&es.svm, &vault).unwrap(), + token_a_offered_amount + ); + + // Step 2: Bob takes the offer + let take_offer_ix = Instruction::new_with_bytes( + es.program_id, + &escrow::instruction::TakeOffer {}.data(), + escrow::accounts::TakeOffer { + taker: es.bob.pubkey(), + maker: es.alice.pubkey(), + token_mint_a: es.mint_a, + token_mint_b: es.mint_b, + taker_token_account_a: es.bob_ata_a, + taker_token_account_b: es.bob_ata_b, + maker_token_account_b: es.alice_ata_b, + offer: offer_pda, + vault, + associated_token_program: ata_program_id(), + token_program: token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut es.svm, + vec![take_offer_ix], + &[&es.payer, &es.bob], + &es.payer.pubkey(), + ) + .unwrap(); + + // Verify Bob received token A from vault + assert_eq!( + get_token_account_balance(&es.svm, &es.bob_ata_a).unwrap(), + token_a_offered_amount + ); + + // Verify Alice received token B from Bob + assert_eq!( + get_token_account_balance(&es.svm, &es.alice_ata_b).unwrap(), + token_b_wanted_amount + ); + + // Verify vault is closed + assert!( + es.svm.get_account(&vault).is_none(), + "Vault should be closed after take_offer" + ); + + // Verify offer account is closed + assert!( + es.svm.get_account(&offer_pda).is_none(), + "Offer should be closed after take_offer" + ); +} diff --git a/tokens/escrow/anchor/register.js b/tokens/escrow/anchor/register.js index 9e438057f..b9c8afd2f 100644 --- a/tokens/escrow/anchor/register.js +++ b/tokens/escrow/anchor/register.js @@ -1,4 +1,4 @@ -import { register } from 'node:module'; -import { pathToFileURL } from 'node:url'; +import { register } from "node:module"; +import { pathToFileURL } from "node:url"; -register('ts-node/esm', pathToFileURL('./')); +register("ts-node/esm", pathToFileURL("./")); diff --git a/tokens/escrow/anchor/tests/bankrun.test.ts b/tokens/escrow/anchor/tests/bankrun.test.ts index d5cfa0768..4a9e34b93 100644 --- a/tokens/escrow/anchor/tests/bankrun.test.ts +++ b/tokens/escrow/anchor/tests/bankrun.test.ts @@ -1,41 +1,38 @@ -import { randomBytes } from 'node:crypto'; -import anchor from '@anchor-lang/core'; +import { randomBytes } from "node:crypto"; +import anchor from "@anchor-lang/core"; + const BN = anchor.BN; + import { createAssociatedTokenAccountIdempotentInstruction, createInitializeMint2Instruction, createMintToInstruction, + getAccount, getAssociatedTokenAddressSync, getMinimumBalanceForRentExemptMint, - getAccount, - unpackAccount, MINT_SIZE, TOKEN_2022_PROGRAM_ID, type TOKEN_PROGRAM_ID, -} from '@solana/spl-token'; -import { - LAMPORTS_PER_SOL, - PublicKey, - SystemProgram, - Transaction, - type TransactionInstruction, -} from '@solana/web3.js'; -import { makeKeypairs } from '@solana-developers/helpers'; -import { BankrunProvider } from 'anchor-bankrun'; -import { assert } from 'chai'; -import { ProgramTestContext, startAnchor } from 'solana-bankrun'; -import type { Escrow } from '../target/types/escrow'; - -const TOKEN_PROGRAM: typeof TOKEN_2022_PROGRAM_ID | typeof TOKEN_PROGRAM_ID = - TOKEN_2022_PROGRAM_ID; -import IDL from '../target/idl/escrow.json' with { type: 'json' }; + unpackAccount, +} from "@solana/spl-token"; +import { LAMPORTS_PER_SOL, PublicKey, SystemProgram, Transaction, type TransactionInstruction } from "@solana/web3.js"; +import { makeKeypairs } from "@solana-developers/helpers"; +import { BankrunProvider } from "anchor-bankrun"; +import { assert } from "chai"; +import { type ProgramTestContext, startAnchor } from "solana-bankrun"; +import type { Escrow } from "../target/types/escrow"; + +const TOKEN_PROGRAM: typeof TOKEN_2022_PROGRAM_ID | typeof TOKEN_PROGRAM_ID = TOKEN_2022_PROGRAM_ID; + +import IDL from "../target/idl/escrow.json" with { type: "json" }; + const PROGRAM_ID = new PublicKey(IDL.address); const getRandomBigNumber = (size = 8) => { return new BN(randomBytes(size)); }; -describe('Escrow Bankrun example', () => { +describe("Escrow Bankrun example", () => { let context: ProgramTestContext; let provider: BankrunProvider; let connection: anchor.web3.Connection; @@ -49,41 +46,24 @@ describe('Escrow Bankrun example', () => { const [alice, bob, tokenMintA, tokenMintB] = makeKeypairs(4); before( - 'Creates Alice and Bob accounts, 2 token mints, and associated token accounts for both tokens for both users', + "Creates Alice and Bob accounts, 2 token mints, and associated token accounts for both tokens for both users", async () => { - context = await startAnchor( - '', - [{ name: 'escrow', programId: PROGRAM_ID }], - [], - ); + context = await startAnchor("", [{ name: "escrow", programId: PROGRAM_ID }], []); provider = new BankrunProvider(context); connection = provider.connection; program = new anchor.Program(IDL, provider); - const [ - aliceTokenAccountA, - aliceTokenAccountB, - bobTokenAccountA, - bobTokenAccountB, - ] = [alice, bob].flatMap((keypair) => - [tokenMintA, tokenMintB].map((mint) => - getAssociatedTokenAddressSync( - mint.publicKey, - keypair.publicKey, - false, - TOKEN_PROGRAM, + const [aliceTokenAccountA, aliceTokenAccountB, bobTokenAccountA, bobTokenAccountB] = [alice, bob].flatMap( + (keypair) => + [tokenMintA, tokenMintB].map((mint) => + getAssociatedTokenAddressSync(mint.publicKey, keypair.publicKey, false, TOKEN_PROGRAM), ), - ), ); // Airdrops to users, and creates two tokens mints 'A' and 'B'" - const minimumLamports = - await getMinimumBalanceForRentExemptMint(connection); + const minimumLamports = await getMinimumBalanceForRentExemptMint(connection); - const sendSolInstructions: Array = [ - alice, - bob, - ].map((account) => + const sendSolInstructions: Array = [alice, bob].map((account) => SystemProgram.transfer({ fromPubkey: provider.publicKey, toPubkey: account.publicKey, @@ -91,10 +71,7 @@ describe('Escrow Bankrun example', () => { }), ); - const createMintInstructions: Array = [ - tokenMintA, - tokenMintB, - ].map((mint) => + const createMintInstructions: Array = [tokenMintA, tokenMintB].map((mint) => SystemProgram.createAccount({ fromPubkey: provider.publicKey, newAccountPubkey: mint.publicKey, @@ -117,13 +94,7 @@ describe('Escrow Bankrun example', () => { ata: bobTokenAccountB, }, ].flatMap((mintDetails) => [ - createInitializeMint2Instruction( - mintDetails.mint, - 6, - mintDetails.authority, - null, - TOKEN_PROGRAM, - ), + createInitializeMint2Instruction(mintDetails.mint, 6, mintDetails.authority, null, TOKEN_PROGRAM), createAssociatedTokenAccountIdempotentInstruction( provider.publicKey, mintDetails.ata, @@ -143,11 +114,7 @@ describe('Escrow Bankrun example', () => { // Add all these instructions to our transaction const tx = new Transaction(); - tx.instructions = [ - ...sendSolInstructions, - ...createMintInstructions, - ...mintTokensInstructions, - ]; + tx.instructions = [...sendSolInstructions, ...createMintInstructions, ...mintTokensInstructions]; await provider.sendAndConfirm(tx, [tokenMintA, tokenMintB, alice, bob]); @@ -173,37 +140,23 @@ describe('Escrow Bankrun example', () => { // Then determine the account addresses we'll use for the offer and the vault const offer = PublicKey.findProgramAddressSync( - [ - Buffer.from('offer'), - accounts.maker.toBuffer(), - offerId.toArrayLike(Buffer, 'le', 8), - ], + [Buffer.from("offer"), accounts.maker.toBuffer(), offerId.toArrayLike(Buffer, "le", 8)], program.programId, )[0]; - const vault = getAssociatedTokenAddressSync( - accounts.tokenMintA, - offer, - true, - TOKEN_PROGRAM, - ); + const vault = getAssociatedTokenAddressSync(accounts.tokenMintA, offer, true, TOKEN_PROGRAM); accounts.offer = offer; accounts.vault = vault; - const transactionSignature = await program.methods + const _transactionSignature = await program.methods .makeOffer(offerId, tokenAOfferedAmount, tokenBWantedAmount) .accounts({ ...accounts }) .signers([alice]) .rpc(); // Check our vault contains the tokens offered - const vaultAccount = await getAccount( - connection, - vault, - 'processed', - TOKEN_PROGRAM, - ); + const vaultAccount = await getAccount(connection, vault, "processed", TOKEN_PROGRAM); const vaultBalance = new BN(vaultAccount.amount.toString()); assert(vaultBalance.eq(tokenAOfferedAmount)); @@ -218,7 +171,7 @@ describe('Escrow Bankrun example', () => { // We'll call this function from multiple tests, so let's seperate it out const take = async () => { - const transactionSignature = await program.methods + const _transactionSignature = await program.methods .takeOffer() .accounts({ ...accounts }) .signers([bob]) @@ -226,38 +179,22 @@ describe('Escrow Bankrun example', () => { // Check the offered tokens are now in Bob's account // (note: there is no before balance as Bob didn't have any offered tokens before the transaction) - const bobTokenAccountInfo = await connection.getAccountInfo( - accounts.takerTokenAccountA, - ); - const bobTokenAccount = unpackAccount( - accounts.takerTokenAccountA, - bobTokenAccountInfo, - TOKEN_PROGRAM, - ); - - const bobTokenAccountBalanceAfter = new BN( - bobTokenAccount.amount.toString(), - ); + const bobTokenAccountInfo = await connection.getAccountInfo(accounts.takerTokenAccountA); + const bobTokenAccount = unpackAccount(accounts.takerTokenAccountA, bobTokenAccountInfo, TOKEN_PROGRAM); + + const bobTokenAccountBalanceAfter = new BN(bobTokenAccount.amount.toString()); assert(bobTokenAccountBalanceAfter.eq(tokenAOfferedAmount)); // Check the wanted tokens are now in Alice's account // (note: there is no before balance as Alice didn't have any wanted tokens before the transaction) - const aliceTokenAccountInfo = await connection.getAccountInfo( - accounts.makerTokenAccountB, - ); - const aliceTokenAccount = unpackAccount( - accounts.makerTokenAccountB, - aliceTokenAccountInfo, - TOKEN_PROGRAM, - ); - - const aliceTokenAccountBalanceAfter = new BN( - aliceTokenAccount.amount.toString(), - ); + const aliceTokenAccountInfo = await connection.getAccountInfo(accounts.makerTokenAccountB); + const aliceTokenAccount = unpackAccount(accounts.makerTokenAccountB, aliceTokenAccountInfo, TOKEN_PROGRAM); + + const aliceTokenAccountBalanceAfter = new BN(aliceTokenAccount.amount.toString()); assert(aliceTokenAccountBalanceAfter.eq(tokenBWantedAmount)); }; - it('Puts the tokens Alice offers into the vault when Alice makes an offer', async () => { + it("Puts the tokens Alice offers into the vault when Alice makes an offer", async () => { await make(); }); diff --git a/tokens/escrow/anchor/tests/escrow.test.ts b/tokens/escrow/anchor/tests/escrow.test.ts index db5f9d96a..c9d44bf7f 100644 --- a/tokens/escrow/anchor/tests/escrow.test.ts +++ b/tokens/escrow/anchor/tests/escrow.test.ts @@ -1,23 +1,16 @@ -import { randomBytes } from 'node:crypto'; -import anchor from '@anchor-lang/core'; +import { randomBytes } from "node:crypto"; +import anchor from "@anchor-lang/core"; + const BN = anchor.BN; -import { - getAssociatedTokenAddressSync, - TOKEN_2022_PROGRAM_ID, - type TOKEN_PROGRAM_ID, -} from '@solana/spl-token'; -import { LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js'; -import { - confirmTransaction, - createAccountsMintsAndTokenAccounts, - makeKeypairs, -} from '@solana-developers/helpers'; -import { assert } from 'chai'; -import type { Escrow } from '../target/types/escrow'; + +import { getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, type TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js"; +import { confirmTransaction, createAccountsMintsAndTokenAccounts, makeKeypairs } from "@solana-developers/helpers"; +import { assert } from "chai"; +import type { Escrow } from "../target/types/escrow"; // Work on both Token Program and new Token Extensions Program -const TOKEN_PROGRAM: typeof TOKEN_2022_PROGRAM_ID | typeof TOKEN_PROGRAM_ID = - TOKEN_2022_PROGRAM_ID; +const TOKEN_PROGRAM: typeof TOKEN_2022_PROGRAM_ID | typeof TOKEN_PROGRAM_ID = TOKEN_2022_PROGRAM_ID; const SECONDS = 1000; @@ -30,7 +23,7 @@ const getRandomBigNumber = (size = 8) => { return new BN(randomBytes(size)); }; -describe('escrow', async () => { +describe("escrow", async () => { // Use the cluster and the keypair from Anchor.toml const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); @@ -59,30 +52,29 @@ describe('escrow', async () => { const tokenBWantedAmount = new BN(1_000_000); before( - 'Creates Alice and Bob accounts, 2 token mints, and associated token accounts for both tokens for both users', + "Creates Alice and Bob accounts, 2 token mints, and associated token accounts for both tokens for both users", async () => { - const usersMintsAndTokenAccounts = - await createAccountsMintsAndTokenAccounts( + const usersMintsAndTokenAccounts = await createAccountsMintsAndTokenAccounts( + [ + // Alice's token balances + [ + // 1_000_000_000 of token A + 1_000_000_000, + // 0 of token B + 0, + ], + // Bob's token balances [ - // Alice's token balances - [ - // 1_000_000_000 of token A - 1_000_000_000, - // 0 of token B - 0, - ], - // Bob's token balances - [ - // 0 of token A - 0, - // 1_000_000_000 of token B - 1_000_000_000, - ], + // 0 of token A + 0, + // 1_000_000_000 of token B + 1_000_000_000, ], - 1 * LAMPORTS_PER_SOL, - connection, - payer, - ); + ], + 1 * LAMPORTS_PER_SOL, + connection, + payer, + ); // Alice will be the maker (creator) of the offer // Bob will be the taker (acceptor) of the offer @@ -120,26 +112,17 @@ describe('escrow', async () => { }, ); - it('Puts the tokens Alice offers into the vault when Alice makes an offer', async () => { + it("Puts the tokens Alice offers into the vault when Alice makes an offer", async () => { // Pick a random ID for the offer we'll make const offerId = getRandomBigNumber(); // Then determine the account addresses we'll use for the offer and the vault const offer = PublicKey.findProgramAddressSync( - [ - Buffer.from('offer'), - accounts.maker.toBuffer(), - offerId.toArrayLike(Buffer, 'le', 8), - ], + [Buffer.from("offer"), accounts.maker.toBuffer(), offerId.toArrayLike(Buffer, "le", 8)], program.programId, )[0]; - const vault = getAssociatedTokenAddressSync( - accounts.tokenMintA, - offer, - true, - TOKEN_PROGRAM, - ); + const vault = getAssociatedTokenAddressSync(accounts.tokenMintA, offer, true, TOKEN_PROGRAM); accounts.offer = offer; accounts.vault = vault; @@ -177,20 +160,14 @@ describe('escrow', async () => { // Check the offered tokens are now in Bob's account // (note: there is no before balance as Bob didn't have any offered tokens before the transaction) - const bobTokenAccountBalanceAfterResponse = - await connection.getTokenAccountBalance(accounts.takerTokenAccountA); - const bobTokenAccountBalanceAfter = new BN( - bobTokenAccountBalanceAfterResponse.value.amount, - ); + const bobTokenAccountBalanceAfterResponse = await connection.getTokenAccountBalance(accounts.takerTokenAccountA); + const bobTokenAccountBalanceAfter = new BN(bobTokenAccountBalanceAfterResponse.value.amount); assert(bobTokenAccountBalanceAfter.eq(tokenAOfferedAmount)); // Check the wanted tokens are now in Alice's account // (note: there is no before balance as Alice didn't have any wanted tokens before the transaction) - const aliceTokenAccountBalanceAfterResponse = - await connection.getTokenAccountBalance(accounts.makerTokenAccountB); - const aliceTokenAccountBalanceAfter = new BN( - aliceTokenAccountBalanceAfterResponse.value.amount, - ); + const aliceTokenAccountBalanceAfterResponse = await connection.getTokenAccountBalance(accounts.makerTokenAccountB); + const aliceTokenAccountBalanceAfter = new BN(aliceTokenAccountBalanceAfterResponse.value.amount); assert(aliceTokenAccountBalanceAfter.eq(tokenBWantedAmount)); }).slow(ANCHOR_SLOW_TEST_THRESHOLD); }); diff --git a/tokens/escrow/native/tests/account.ts b/tokens/escrow/native/tests/account.ts index 507ad647c..0e88dc80b 100644 --- a/tokens/escrow/native/tests/account.ts +++ b/tokens/escrow/native/tests/account.ts @@ -1,13 +1,13 @@ -import * as borsh from 'borsh'; +import * as borsh from "borsh"; export const OfferSchema = { struct: { - id: 'u64', - maker: { array: { type: 'u8', len: 32 } }, - token_mint_a: { array: { type: 'u8', len: 32 } }, - token_mint_b: { array: { type: 'u8', len: 32 } }, - token_b_wanted_amount: 'u64', - bump: 'u8', + id: "u64", + maker: { array: { type: "u8", len: 32 } }, + token_mint_a: { array: { type: "u8", len: 32 } }, + token_mint_b: { array: { type: "u8", len: 32 } }, + token_b_wanted_amount: "u64", + bump: "u8", }, }; diff --git a/tokens/escrow/native/tests/instruction.ts b/tokens/escrow/native/tests/instruction.ts index 7b033c089..19fa0e753 100644 --- a/tokens/escrow/native/tests/instruction.ts +++ b/tokens/escrow/native/tests/instruction.ts @@ -1,7 +1,7 @@ -import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token'; -import { PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js'; -import BN from 'bn.js'; -import * as borsh from 'borsh'; +import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { type PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js"; +import type BN from "bn.js"; +import * as borsh from "borsh"; enum EscrowInstruction { MakeOffer = 0, @@ -10,16 +10,16 @@ enum EscrowInstruction { const MakeOfferSchema = { struct: { - instruction: 'u8', - id: 'u64', - token_a_offered_amount: 'u64', - token_b_wanted_amount: 'u64', + instruction: "u8", + id: "u64", + token_a_offered_amount: "u64", + token_b_wanted_amount: "u64", }, }; const TakeOfferSchema = { struct: { - instruction: 'u8', + instruction: "u8", }, }; @@ -57,7 +57,11 @@ export function buildMakeOffer(props: { { pubkey: props.maker, isSigner: true, isWritable: true }, { pubkey: props.payer, isSigner: true, isWritable: true }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, - { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, + { + pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, ], programId: props.programId, @@ -95,7 +99,11 @@ export function buildTakeOffer(props: { { pubkey: props.taker, isSigner: true, isWritable: true }, { pubkey: props.payer, isSigner: true, isWritable: true }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, - { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, + { + pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, ], programId: props.programId, diff --git a/tokens/escrow/native/tests/test.ts b/tokens/escrow/native/tests/test.ts index 5ae49b304..62f40bad9 100644 --- a/tokens/escrow/native/tests/test.ts +++ b/tokens/escrow/native/tests/test.ts @@ -1,17 +1,17 @@ -import { describe, test } from 'node:test'; -import { AccountLayout } from '@solana/spl-token'; -import { PublicKey, Transaction } from '@solana/web3.js'; -import { assert } from 'chai'; -import { start } from 'solana-bankrun'; -import * as borsh from 'borsh'; -import { OfferSchema, type OfferRaw } from './account'; -import { buildMakeOffer, buildTakeOffer } from './instruction'; -import { createValues, mintingTokens } from './utils'; - -describe('Escrow!', async () => { +import { describe, test } from "node:test"; +import { AccountLayout } from "@solana/spl-token"; +import { PublicKey, Transaction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { assert } from "chai"; +import { start } from "solana-bankrun"; +import { type OfferRaw, OfferSchema } from "./account"; +import { buildMakeOffer, buildTakeOffer } from "./instruction"; +import { createValues, mintingTokens } from "./utils"; + +describe("Escrow!", async () => { const values = createValues(); - const context = await start([{ name: 'escrow_native_program', programId: values.programId }], []); + const context = await start([{ name: "escrow_native_program", programId: values.programId }], []); const client = context.banksClient; const payer = context.payer; @@ -19,7 +19,7 @@ describe('Escrow!', async () => { console.log(`Program Address : ${values.programId}`); console.log(`Payer Address : ${payer.publicKey}`); - test('mint tokens to maker and taker', async () => { + test("mint tokens to maker and taker", async () => { // mint token a to maker account await mintingTokens({ context, @@ -35,7 +35,7 @@ describe('Escrow!', async () => { }); }); - test('Make Offer', async () => { + test("Make Offer", async () => { const ix = buildMakeOffer({ id: values.id, maker: values.maker.publicKey, @@ -63,16 +63,16 @@ describe('Escrow!', async () => { const vaultInfo = await client.getAccount(values.vault); const vaultTokenAccount = AccountLayout.decode(vaultInfo.data); - assert(offer.id.toString() === values.id.toString(), 'wrong id'); + assert(offer.id.toString() === values.id.toString(), "wrong id"); // borsh deserializes pubkeys as raw byte arrays, wrap in PublicKey for comparison - assert(new PublicKey(offer.maker).toBase58() === values.maker.publicKey.toBase58(), 'maker key does not match'); - assert(new PublicKey(offer.token_mint_a).toBase58() === values.mintAKeypair.publicKey.toBase58(), 'wrong mint A'); - assert(new PublicKey(offer.token_mint_b).toBase58() === values.mintBKeypair.publicKey.toBase58(), 'wrong mint B'); - assert(offer.token_b_wanted_amount.toString() === values.amountB.toString(), 'unexpected amount B'); - assert(vaultTokenAccount.amount.toString() === values.amountA.toString(), 'unexpected amount A'); + assert(new PublicKey(offer.maker).toBase58() === values.maker.publicKey.toBase58(), "maker key does not match"); + assert(new PublicKey(offer.token_mint_a).toBase58() === values.mintAKeypair.publicKey.toBase58(), "wrong mint A"); + assert(new PublicKey(offer.token_mint_b).toBase58() === values.mintBKeypair.publicKey.toBase58(), "wrong mint B"); + assert(offer.token_b_wanted_amount.toString() === values.amountB.toString(), "unexpected amount B"); + assert(vaultTokenAccount.amount.toString() === values.amountA.toString(), "unexpected amount A"); }); - test('Take Offer', async () => { + test("Take Offer", async () => { const ix = buildTakeOffer({ maker: values.maker.publicKey, offer: values.offer, @@ -95,10 +95,10 @@ describe('Escrow!', async () => { await client.processTransaction(tx); const offerInfo = await client.getAccount(values.offer); - assert(offerInfo === null, 'offer account not closed'); + assert(offerInfo === null, "offer account not closed"); const vaultInfo = await client.getAccount(values.vault); - assert(vaultInfo === null, 'vault account not closed'); + assert(vaultInfo === null, "vault account not closed"); const makerTokenBInfo = await client.getAccount(values.makerAccountB); const makerTokenAccountB = AccountLayout.decode(makerTokenBInfo.data); @@ -106,7 +106,7 @@ describe('Escrow!', async () => { const takerTokenAInfo = await client.getAccount(values.takerAccountA); const takerTokenAccountA = AccountLayout.decode(takerTokenAInfo.data); - assert(takerTokenAccountA.amount.toString() === values.amountA.toString(), 'unexpected amount a'); - assert(makerTokenAccountB.amount.toString() === values.amountB.toString(), 'unexpected amount b'); + assert(takerTokenAccountA.amount.toString() === values.amountA.toString(), "unexpected amount a"); + assert(makerTokenAccountB.amount.toString() === values.amountB.toString(), "unexpected amount b"); }); }); diff --git a/tokens/escrow/native/tests/utils.ts b/tokens/escrow/native/tests/utils.ts index b21d7d1ef..57da01343 100644 --- a/tokens/escrow/native/tests/utils.ts +++ b/tokens/escrow/native/tests/utils.ts @@ -6,19 +6,19 @@ import { getAssociatedTokenAddressSync, MINT_SIZE, TOKEN_PROGRAM_ID, -} from '@solana/spl-token'; -import { Keypair, PublicKey, type Signer, SystemProgram, Transaction } from '@solana/web3.js'; -import BN from 'bn.js'; -import { ProgramTestContext } from 'solana-bankrun'; +} from "@solana/spl-token"; +import { Keypair, PublicKey, type Signer, SystemProgram, Transaction } from "@solana/web3.js"; +import BN from "bn.js"; +import type { ProgramTestContext } from "solana-bankrun"; export async function sleep(seconds: number) { new Promise((resolve) => setTimeout(resolve, seconds * 1000)); } -export const expectRevert = async (promise: Promise) => { +export const expectRevert = async (promise: Promise) => { try { await promise; - throw new Error('Expected a revert'); + throw new Error("Expected a revert"); } catch { return; } @@ -50,7 +50,13 @@ export const mintingTokens = async ({ lamports: new BN(lamports.toString()).toNumber(), programId: TOKEN_PROGRAM_ID, }), - createInitializeMint2Instruction(mint.publicKey, decimals, context.payer.publicKey, context.payer.publicKey, TOKEN_PROGRAM_ID), + createInitializeMint2Instruction( + mint.publicKey, + decimals, + context.payer.publicKey, + context.payer.publicKey, + TOKEN_PROGRAM_ID, + ), ); transaction.recentBlockhash = context.lastBlockhash; transaction.sign(context.payer, mint); @@ -82,7 +88,9 @@ export const mintingTokens = async ({ } async function mintTo(context: ProgramTestContext, mint: PublicKey, destination: PublicKey, amount: number | bigint) { - const transaction = new Transaction().add(createMintToInstruction(mint, destination, context.payer.publicKey, amount, [], TOKEN_PROGRAM_ID)); + const transaction = new Transaction().add( + createMintToInstruction(mint, destination, context.payer.publicKey, amount, [], TOKEN_PROGRAM_ID), + ); transaction.recentBlockhash = context.lastBlockhash; transaction.sign(context.payer); @@ -138,7 +146,10 @@ export function createValues(defaults?: TestValuesDefaults): TestValues { mintBKeypair = Keypair.generate(); } - const offer = PublicKey.findProgramAddressSync([Buffer.from('offer'), maker.publicKey.toBuffer(), Buffer.from(id.toArray('le', 8))], programId)[0]; + const offer = PublicKey.findProgramAddressSync( + [Buffer.from("offer"), maker.publicKey.toBuffer(), Buffer.from(id.toArray("le", 8))], + programId, + )[0]; return { id, diff --git a/tokens/external-delegate-token-master/anchor/Anchor.toml b/tokens/external-delegate-token-master/anchor/Anchor.toml index 59bdd22d4..f69a53548 100644 --- a/tokens/external-delegate-token-master/anchor/Anchor.toml +++ b/tokens/external-delegate-token-master/anchor/Anchor.toml @@ -2,17 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false [programs.localnet] -external_delegate_token_master = "FYPkt5VWMvtyWZDMGCwoKFkE3wXTzphicTpnNGuHWVbD" - -# [registry] section removed — no longer used in Anchor 1.0 +external_delegate_token_master = "85ucSW6NvhoAUYMr9QBXggsGLh3h2EqdWSDuGLzPetFd" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "yarn test" \ No newline at end of file +test = "cargo test" + +[hooks] diff --git a/tokens/external-delegate-token-master/anchor/package.json b/tokens/external-delegate-token-master/anchor/package.json index 7b479380b..ac1e4fc12 100644 --- a/tokens/external-delegate-token-master/anchor/package.json +++ b/tokens/external-delegate-token-master/anchor/package.json @@ -1,35 +1,35 @@ { - "type": "module", - "name": "external-delegate-token-master", - "version": "1.0.0", - "license": "MIT", - "scripts": { - "test": "jest --detectOpenHandles --forceExit", - "test:watch": "jest --watch", - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check", - "build": "anchor build" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.3.9", - "@solana/web3.js": "^1.98.4", - "ethers": "^5.7.2" - }, - "devDependencies": { - "@babel/core": "^7.23.7", - "@babel/preset-env": "^7.23.7", - "@babel/preset-typescript": "^7.23.7", - "@testing-library/jest-dom": "^6.1.6", - "@types/chai": "^4.3.0", - "@types/jest": "^29.5.11", - "@types/node": "^18.0.0", - "babel-jest": "^29.7.0", - "chai": "^4.3.4", - "jest": "^29.7.0", - "prettier": "^2.6.2", - "solana-bankrun": "^0.2.0", - "ts-jest": "^29.1.1", - "typescript": "^5.3.3" - } + "type": "module", + "name": "external-delegate-token-master", + "version": "1.0.0", + "license": "MIT", + "scripts": { + "test": "jest --detectOpenHandles --forceExit", + "test:watch": "jest --watch", + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check", + "build": "anchor build" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.3.9", + "@solana/web3.js": "^1.98.4", + "ethers": "^5.7.2" + }, + "devDependencies": { + "@babel/core": "^7.23.7", + "@babel/preset-env": "^7.23.7", + "@babel/preset-typescript": "^7.23.7", + "@testing-library/jest-dom": "^6.1.6", + "@types/chai": "^4.3.0", + "@types/jest": "^29.5.11", + "@types/node": "^18.0.0", + "babel-jest": "^29.7.0", + "chai": "^4.3.4", + "jest": "^29.7.0", + "prettier": "^2.6.2", + "solana-bankrun": "^0.2.0", + "ts-jest": "^29.1.1", + "typescript": "^5.3.3" + } } diff --git a/tokens/external-delegate-token-master/anchor/pnpm-lock.yaml b/tokens/external-delegate-token-master/anchor/pnpm-lock.yaml index 8d6c1b87a..715bcac46 100644 --- a/tokens/external-delegate-token-master/anchor/pnpm-lock.yaml +++ b/tokens/external-delegate-token-master/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.3.9 version: 0.3.11(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -73,18 +73,18 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/code-frame@7.27.1': @@ -2271,16 +2271,16 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -2298,7 +2298,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/code-frame@7.27.1': dependencies: diff --git a/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/Cargo.toml b/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/Cargo.toml index 45a99dc2e..d9d1f08ff 100644 --- a/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/Cargo.toml +++ b/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/Cargo.toml @@ -20,11 +20,17 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } -anchor-spl = { version = "1.0.0-rc.5", features = ["metadata"] } +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = { version = "1.0.0", features = ["metadata"] } sha3 = "0.10.8" solana-secp256k1-recover = "2.0.0" +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/src/lib.rs b/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/src/lib.rs index 425bf8aee..ac602dcc9 100644 --- a/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/src/lib.rs +++ b/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/src/lib.rs @@ -4,7 +4,7 @@ use anchor_spl::token::{Token, TokenAccount, Transfer}; use sha3::{Digest, Keccak256}; use solana_secp256k1_recover::secp256k1_recover; -declare_id!("FYPkt5VWMvtyWZDMGCwoKFkE3wXTzphicTpnNGuHWVbD"); +declare_id!("85ucSW6NvhoAUYMr9QBXggsGLh3h2EqdWSDuGLzPetFd"); #[program] pub mod external_delegate_token_master { diff --git a/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/tests/test_external_delegate.rs b/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/tests/test_external_delegate.rs new file mode 100644 index 000000000..edc4ae81b --- /dev/null +++ b/tokens/external-delegate-token-master/anchor/programs/external-delegate-token-master/tests/test_external_delegate.rs @@ -0,0 +1,224 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{ + create_associated_token_account, create_token_mint, create_wallet, + get_token_account_balance, mint_tokens_to_token_account, send_transaction_from_instructions, + }, + solana_signer::Signer, +}; + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn derive_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey { + let ata_program: Pubkey = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap(); + let (ata, _bump) = Pubkey::find_program_address( + &[wallet.as_ref(), token_program_id().as_ref(), mint.as_ref()], + &ata_program, + ); + ata +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = external_delegate_token_master::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/external_delegate_token_master.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_initialize_user_account() { + let (mut svm, program_id, authority) = setup(); + let user_account = Keypair::new(); + + let init_ix = Instruction::new_with_bytes( + program_id, + &external_delegate_token_master::instruction::Initialize {}.data(), + external_delegate_token_master::accounts::Initialize { + user_account: user_account.pubkey(), + authority: authority.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![init_ix], + &[&authority, &user_account], + &authority.pubkey(), + ) + .unwrap(); + + // Verify the account was created + let account_data = svm + .get_account(&user_account.pubkey()) + .expect("User account should exist"); + + // Skip 8-byte discriminator + let data = &account_data.data[8..]; + let stored_authority = Pubkey::try_from(&data[0..32]).unwrap(); + assert_eq!(stored_authority, authority.pubkey()); + + // ethereum_address: [u8; 20] — should be all zeros + let eth_addr = &data[32..52]; + assert_eq!(eth_addr, &[0u8; 20]); +} + +#[test] +fn test_set_ethereum_address() { + let (mut svm, program_id, authority) = setup(); + let user_account = Keypair::new(); + + // Initialize + let init_ix = Instruction::new_with_bytes( + program_id, + &external_delegate_token_master::instruction::Initialize {}.data(), + external_delegate_token_master::accounts::Initialize { + user_account: user_account.pubkey(), + authority: authority.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![init_ix], + &[&authority, &user_account], + &authority.pubkey(), + ) + .unwrap(); + + // Set ethereum address + let ethereum_address: [u8; 20] = [ + 0x1C, 0x8c, 0xd0, 0xc3, 0x8F, 0x8D, 0xE3, 0x5d, 0x60, 0x56, 0xc7, 0xC7, 0xaB, 0xFa, + 0x7e, 0x65, 0xD2, 0x60, 0xE8, 0x16, + ]; + + let set_eth_ix = Instruction::new_with_bytes( + program_id, + &external_delegate_token_master::instruction::SetEthereumAddress { + ethereum_address, + } + .data(), + external_delegate_token_master::accounts::SetEthereumAddress { + user_account: user_account.pubkey(), + authority: authority.pubkey(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![set_eth_ix], + &[&authority], + &authority.pubkey(), + ) + .unwrap(); + + // Verify + let account_data = svm + .get_account(&user_account.pubkey()) + .expect("User account should exist"); + let data = &account_data.data[8..]; + let stored_eth_addr = &data[32..52]; + assert_eq!(stored_eth_addr, ðereum_address); +} + +#[test] +fn test_authority_transfer() { + let (mut svm, program_id, authority) = setup(); + let user_account = Keypair::new(); + + // Initialize user account + let init_ix = Instruction::new_with_bytes( + program_id, + &external_delegate_token_master::instruction::Initialize {}.data(), + external_delegate_token_master::accounts::Initialize { + user_account: user_account.pubkey(), + authority: authority.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![init_ix], + &[&authority, &user_account], + &authority.pubkey(), + ) + .unwrap(); + + // user_pda is derived from user_account key + let (user_pda, _bump) = + Pubkey::find_program_address(&[user_account.pubkey().as_ref()], &program_id); + + // Create mint and token accounts using Kite + let mint_pubkey = create_token_mint(&mut svm, &authority, 6, None).unwrap(); + + // Create ATA for the user_pda + let user_pda_ata = + create_associated_token_account(&mut svm, &user_pda, &mint_pubkey, &authority).unwrap(); + + // Mint tokens to user_pda's ATA + let mint_amount: u64 = 1_000_000_000; + mint_tokens_to_token_account(&mut svm, &mint_pubkey, &user_pda_ata, mint_amount, &authority) + .unwrap(); + + // Create recipient ATA + let recipient = Keypair::new(); + let recipient_ata = + create_associated_token_account(&mut svm, &recipient.pubkey(), &mint_pubkey, &authority) + .unwrap(); + + // Perform authority transfer + let transfer_amount: u64 = 500_000_000; + let authority_transfer_ix = Instruction::new_with_bytes( + program_id, + &external_delegate_token_master::instruction::AuthorityTransfer { + amount: transfer_amount, + } + .data(), + external_delegate_token_master::accounts::AuthorityTransfer { + user_account: user_account.pubkey(), + authority: authority.pubkey(), + user_token_account: user_pda_ata, + recipient_token_account: recipient_ata, + user_pda, + token_program: token_program_id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![authority_transfer_ix], + &[&authority], + &authority.pubkey(), + ) + .unwrap(); + + // Verify recipient received tokens + assert_eq!( + get_token_account_balance(&svm, &recipient_ata).unwrap(), + transfer_amount + ); + + // Verify user_pda's balance decreased + assert_eq!( + get_token_account_balance(&svm, &user_pda_ata).unwrap(), + mint_amount - transfer_amount + ); +} diff --git a/tokens/external-delegate-token-master/anchor/tests/external-delegate-token-master.test.ts b/tokens/external-delegate-token-master/anchor/tests/external-delegate-token-master.test.ts index 3b9334897..713f9db17 100644 --- a/tokens/external-delegate-token-master/anchor/tests/external-delegate-token-master.test.ts +++ b/tokens/external-delegate-token-master/anchor/tests/external-delegate-token-master.test.ts @@ -1,12 +1,13 @@ -import { createMint, getOrCreateAssociatedTokenAccount, mintTo } from '@solana/spl-token'; -import { Connection, Keypair, PublicKey, SystemProgram } from '@solana/web3.js'; -import { expect } from 'chai'; -import { start } from 'solana-bankrun'; +import { createMint, getOrCreateAssociatedTokenAccount, mintTo } from "@solana/spl-token"; +import { Connection, Keypair, PublicKey, SystemProgram } from "@solana/web3.js"; +import { expect } from "chai"; +import { start } from "solana-bankrun"; jest.setTimeout(30000); // Set timeout to 30 seconds const ACCOUNT_SIZE = 8 + 32 + 20; // Define your account size here +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 async function retryWithBackoff(fn: () => Promise, retries = 5, delay = 500): Promise { try { return await fn(); @@ -17,8 +18,10 @@ async function retryWithBackoff(fn: () => Promise, retries = 5, delay = 500 } } -describe('External Delegate Token Master Tests', () => { +describe("External Delegate Token Master Tests", () => { + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 let context: any; + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 let _program: any; let authority: Keypair; let userAccount: Keypair; @@ -34,15 +37,15 @@ describe('External Delegate Token Master Tests', () => { const programs = [ { - name: 'external_delegate_token_master', - programId: new PublicKey('FYPkt5VWMvtyWZDMGCwoKFkE3wXTzphicTpnNGuHWVbD'), - program: 'target/deploy/external_delegate_token_master.so', + name: "external_delegate_token_master", + programId: new PublicKey("FYPkt5VWMvtyWZDMGCwoKFkE3wXTzphicTpnNGuHWVbD"), + program: "target/deploy/external_delegate_token_master.so", }, ]; context = await retryWithBackoff(async () => await start(programs, [])); - const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); + const connection = new Connection("https://api.devnet.solana.com", "confirmed"); context.connection = connection; // Airdrop SOL to authority with retry logic @@ -64,7 +67,9 @@ describe('External Delegate Token Master Tests', () => { _recipientTokenAccount = recipientTokenAccountInfo.address; // Mint tokens to the user's account - await retryWithBackoff(async () => await mintTo(connection, authority, mint, userTokenAccount, authority, 1000000000)); + await retryWithBackoff( + async () => await mintTo(connection, authority, mint, userTokenAccount, authority, 1000000000), + ); // Find program-derived address (PDA) [_userPda, _bumpSeed] = await retryWithBackoff( @@ -72,7 +77,7 @@ describe('External Delegate Token Master Tests', () => { ); }); - it('should initialize user account', async () => { + it("should initialize user account", async () => { const space = ACCOUNT_SIZE; const rentExempt = await retryWithBackoff(async () => { return await context.connection.getMinimumBalanceForRentExemption(space); @@ -102,8 +107,8 @@ describe('External Delegate Token Master Tests', () => { expect(account.ethereumAddress).to.deep.equal(new Array(20).fill(0)); }); - it('should set ethereum address', async () => { - const ethereumAddress = Buffer.from('1C8cd0c38F8DE35d6056c7C7aBFa7e65D260E816', 'hex'); + it("should set ethereum address", async () => { + const ethereumAddress = Buffer.from("1C8cd0c38F8DE35d6056c7C7aBFa7e65D260E816", "hex"); await context.program.methods .setEthereumAddress(ethereumAddress) @@ -118,7 +123,7 @@ describe('External Delegate Token Master Tests', () => { expect(account.ethereumAddress).to.deep.equal(Array.from(ethereumAddress)); }); - it('should perform authority transfer', async () => { + it("should perform authority transfer", async () => { const newAuthority = Keypair.generate(); await context.program.methods @@ -135,7 +140,7 @@ describe('External Delegate Token Master Tests', () => { }); afterEach(async () => { - if (context && typeof context.terminate === 'function') { + if (context && typeof context.terminate === "function") { await context.terminate(); } }); diff --git a/tokens/external-delegate-token-master/anchor/tests/types.ts b/tokens/external-delegate-token-master/anchor/tests/types.ts index 191287b59..af8faa3a2 100644 --- a/tokens/external-delegate-token-master/anchor/tests/types.ts +++ b/tokens/external-delegate-token-master/anchor/tests/types.ts @@ -1,7 +1,8 @@ // tests/types.ts -import { PublicKey } from '@solana/web3.js'; +import type { PublicKey } from "@solana/web3.js"; export interface ProgramTestContext { + // biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 connection: any; programs: { programId: PublicKey; diff --git a/tokens/nft-minter/anchor/Anchor.toml b/tokens/nft-minter/anchor/Anchor.toml index 8335d19a6..01e0aa447 100644 --- a/tokens/nft-minter/anchor/Anchor.toml +++ b/tokens/nft-minter/anchor/Anchor.toml @@ -4,19 +4,15 @@ solana_version = "3.1.8" [features] resolution = true skip-lint = false -seeds = true [programs.localnet] -nft_minter = "52quezNUzc1Ej6Jh6L4bvtxPW8j6TEFHuLVAWiFvdnsc" - -# [registry] section removed — no longer used in Anchor 1.0 +nft_minter = "H7AFrTXDtmpPoc2kHD8hkEF1i8Pbhi17QUczbkWYYFBV" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -# Only run bankrun tests — the validator tests (test.ts) need Metaplex Token -# Metadata cloned from mainnet which is too slow/unreliable in CI. -# bankrun.test.ts uses a local fixture (tests/fixtures/token_metadata.so). -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/bankrun.test.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/nft-minter/anchor/package.json b/tokens/nft-minter/anchor/package.json index 3b548a433..c5772e47f 100644 --- a/tokens/nft-minter/anchor/package.json +++ b/tokens/nft-minter/anchor/package.json @@ -1,20 +1,20 @@ { - "type": "module", - "scripts": { - "postinstall": "zx prepare.mjs" - }, - "devDependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.3.11", - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3", - "zx": "^8.1.4" - } + "type": "module", + "scripts": { + "postinstall": "zx prepare.mjs" + }, + "devDependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.3.11", + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3", + "zx": "^8.1.4" + } } diff --git a/tokens/nft-minter/anchor/pnpm-lock.yaml b/tokens/nft-minter/anchor/pnpm-lock.yaml index eed086d2d..6ac87288e 100644 --- a/tokens/nft-minter/anchor/pnpm-lock.yaml +++ b/tokens/nft-minter/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.3.11 version: 0.3.11(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -47,18 +47,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -839,16 +839,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -866,7 +866,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/nft-minter/anchor/prepare.mjs b/tokens/nft-minter/anchor/prepare.mjs index 7c5ec464b..fb6b26225 100644 --- a/tokens/nft-minter/anchor/prepare.mjs +++ b/tokens/nft-minter/anchor/prepare.mjs @@ -1,17 +1,17 @@ #!/usr/bin/env zx -import { mkdir, rm } from 'node:fs/promises'; -import { join } from 'node:path'; -import { $ } from 'zx'; +import { mkdir, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { $ } from "zx"; const programs = [ { - id: 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', - name: 'token_metadata.so', + id: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", + name: "token_metadata.so", }, ]; -const outputDir = 'tests/fixtures'; +const outputDir = "tests/fixtures"; const overwrite = true; try { diff --git a/tokens/nft-minter/anchor/programs/nft-minter/Cargo.toml b/tokens/nft-minter/anchor/programs/nft-minter/Cargo.toml index 1f2a9e5b6..bafce2b5f 100644 --- a/tokens/nft-minter/anchor/programs/nft-minter/Cargo.toml +++ b/tokens/nft-minter/anchor/programs/nft-minter/Cargo.toml @@ -20,9 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } -anchor-spl = { version = "1.0.0-rc.5", features = ["metadata"] } +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = { version = "1.0.0", features = ["metadata"] } + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/nft-minter/anchor/programs/nft-minter/src/lib.rs b/tokens/nft-minter/anchor/programs/nft-minter/src/lib.rs index 3f5af3893..443bc97e2 100644 --- a/tokens/nft-minter/anchor/programs/nft-minter/src/lib.rs +++ b/tokens/nft-minter/anchor/programs/nft-minter/src/lib.rs @@ -11,7 +11,7 @@ use { }, }; -declare_id!("52quezNUzc1Ej6Jh6L4bvtxPW8j6TEFHuLVAWiFvdnsc"); +declare_id!("H7AFrTXDtmpPoc2kHD8hkEF1i8Pbhi17QUczbkWYYFBV"); #[program] pub mod nft_minter { diff --git a/tokens/nft-minter/anchor/programs/nft-minter/tests/test_nft_minter.rs b/tokens/nft-minter/anchor/programs/nft-minter/tests/test_nft_minter.rs new file mode 100644 index 000000000..a619ac936 --- /dev/null +++ b/tokens/nft-minter/anchor/programs/nft-minter/tests/test_nft_minter.rs @@ -0,0 +1,145 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{ + create_wallet, get_token_account_balance, send_transaction_from_instructions, + }, + solana_signer::Signer, +}; + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn ata_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn metadata_program_id() -> Pubkey { + "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + .parse() + .unwrap() +} + +fn rent_sysvar_id() -> Pubkey { + "SysvarRent111111111111111111111111111111111" + .parse() + .unwrap() +} + +fn derive_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey { + let (ata, _bump) = Pubkey::find_program_address( + &[wallet.as_ref(), token_program_id().as_ref(), mint.as_ref()], + &ata_program_id(), + ); + ata +} + +fn derive_metadata_pda(mint: &Pubkey) -> Pubkey { + let metadata_pid = metadata_program_id(); + let (pda, _bump) = Pubkey::find_program_address( + &[b"metadata", metadata_pid.as_ref(), mint.as_ref()], + &metadata_pid, + ); + pda +} + +fn derive_edition_pda(mint: &Pubkey) -> Pubkey { + let metadata_pid = metadata_program_id(); + let (pda, _bump) = Pubkey::find_program_address( + &[ + b"metadata", + metadata_pid.as_ref(), + mint.as_ref(), + b"edition", + ], + &metadata_pid, + ); + pda +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = nft_minter::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/nft_minter.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let metadata_bytes = include_bytes!("../../../tests/fixtures/mpl_token_metadata.so"); + svm.add_program(metadata_program_id(), metadata_bytes) + .unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_mint_nft() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + + let metadata_account = derive_metadata_pda(&mint_keypair.pubkey()); + let edition_account = derive_edition_pda(&mint_keypair.pubkey()); + let associated_token_account = derive_ata(&payer.pubkey(), &mint_keypair.pubkey()); + + let instruction = Instruction::new_with_bytes( + program_id, + &nft_minter::instruction::MintNft { + nft_name: "Homer NFT".to_string(), + nft_symbol: "HOMR".to_string(), + nft_uri: "https://example.com/nft.json".to_string(), + } + .data(), + nft_minter::accounts::CreateToken { + payer: payer.pubkey(), + metadata_account, + edition_account, + mint_account: mint_keypair.pubkey(), + associated_token_account, + token_program: token_program_id(), + token_metadata_program: metadata_program_id(), + associated_token_program: ata_program_id(), + system_program: system_program::id(), + rent: rent_sysvar_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &mint_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Verify the mint account exists (NFT = 0 decimals) + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should exist"); + assert!(!mint_account.data.is_empty()); + + // Verify the metadata account was created + let meta_account = svm + .get_account(&metadata_account) + .expect("Metadata account should exist"); + assert!(!meta_account.data.is_empty()); + + // Verify the edition account was created + let edition = svm + .get_account(&edition_account) + .expect("Edition account should exist"); + assert!(!edition.data.is_empty()); + + // Verify 1 NFT was minted to the associated token account + let balance = get_token_account_balance(&svm, &associated_token_account).unwrap(); + assert_eq!(balance, 1, "Should have exactly 1 NFT"); +} diff --git a/tokens/nft-minter/anchor/tests/bankrun.test.ts b/tokens/nft-minter/anchor/tests/bankrun.test.ts index 77a9e535a..63958d563 100644 --- a/tokens/nft-minter/anchor/tests/bankrun.test.ts +++ b/tokens/nft-minter/anchor/tests/bankrun.test.ts @@ -8,9 +8,7 @@ import type { NftMinter } from "../target/types/nft_minter"; // Use require() for JSON import — "import ... with { type: "json" }" needs TS 5.3+ const IDL = require("../target/idl/nft_minter.json"); const PROGRAM_ID = new PublicKey(IDL.address); -const METADATA_PROGRAM_ID = new PublicKey( - "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", -); +const METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); describe("NFT bankrun Minter", async () => { const context = await startAnchor( @@ -38,10 +36,7 @@ describe("NFT bankrun Minter", async () => { const mintKeypair = new Keypair(); // Derive the associated token address account for the mint and payer. - const associatedTokenAccountAddress = getAssociatedTokenAddressSync( - mintKeypair.publicKey, - payer.publicKey, - ); + const associatedTokenAccountAddress = getAssociatedTokenAddressSync(mintKeypair.publicKey, payer.publicKey); const transactionSignature = await program.methods .mintNft(metadata.name, metadata.symbol, metadata.uri) diff --git a/tokens/nft-minter/anchor/tests/fixtures/mpl_token_metadata.so b/tokens/nft-minter/anchor/tests/fixtures/mpl_token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/nft-minter/anchor/tests/fixtures/mpl_token_metadata.so differ diff --git a/tokens/nft-minter/anchor/tests/fixtures/token_metadata.so b/tokens/nft-minter/anchor/tests/fixtures/token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/nft-minter/anchor/tests/fixtures/token_metadata.so differ diff --git a/tokens/nft-minter/anchor/tests/test.ts b/tokens/nft-minter/anchor/tests/test.ts index 4b0bd3fda..08d3f3453 100644 --- a/tokens/nft-minter/anchor/tests/test.ts +++ b/tokens/nft-minter/anchor/tests/test.ts @@ -1,9 +1,9 @@ -import * as anchor from '@anchor-lang/core'; -import { getAssociatedTokenAddressSync } from '@solana/spl-token'; -import { Keypair } from '@solana/web3.js'; -import type { NftMinter } from '../target/types/nft_minter'; +import * as anchor from "@anchor-lang/core"; +import { getAssociatedTokenAddressSync } from "@solana/spl-token"; +import { Keypair } from "@solana/web3.js"; +import type { NftMinter } from "../target/types/nft_minter"; -describe('NFT Minter', () => { +describe("NFT Minter", () => { const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); const payer = provider.wallet as anchor.Wallet; @@ -11,12 +11,12 @@ describe('NFT Minter', () => { // The metadata for our NFT const metadata = { - name: 'Homer NFT', - symbol: 'HOMR', - uri: 'https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json', + name: "Homer NFT", + symbol: "HOMR", + uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json", }; - it('Create an NFT!', async () => { + it("Create an NFT!", async () => { // Generate a keypair to use as the address of our mint account const mintKeypair = new Keypair(); @@ -33,7 +33,7 @@ describe('NFT Minter', () => { .signers([mintKeypair]) .rpc({ skipPreflight: true }); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${mintKeypair.publicKey}`); console.log(` Transaction Signature: ${transactionSignature}`); }); diff --git a/tokens/nft-minter/native/tests/instructions.ts b/tokens/nft-minter/native/tests/instructions.ts index 72e047d58..91caed0d2 100644 --- a/tokens/nft-minter/native/tests/instructions.ts +++ b/tokens/nft-minter/native/tests/instructions.ts @@ -1,4 +1,4 @@ -import * as borsh from 'borsh'; +import * as borsh from "borsh"; export enum NftMinterInstruction { Create = 0, @@ -7,14 +7,14 @@ export enum NftMinterInstruction { export const CreateTokenArgsSchema = { struct: { - instruction: 'u8', - token_title: 'string', - token_symbol: 'string', - token_uri: 'string', + instruction: "u8", + token_title: "string", + token_symbol: "string", + token_uri: "string", }, }; -export const MintToArgsSchema = { struct: { instruction: 'u8' } }; +export const MintToArgsSchema = { struct: { instruction: "u8" } }; export function borshSerialize(schema: borsh.Schema, data: object): Buffer { return Buffer.from(borsh.serialize(schema, data)); diff --git a/tokens/nft-minter/native/tests/test.ts b/tokens/nft-minter/native/tests/test.ts index cc26800f9..040f11cc5 100644 --- a/tokens/nft-minter/native/tests/test.ts +++ b/tokens/nft-minter/native/tests/test.ts @@ -1,6 +1,6 @@ -import { Buffer } from 'node:buffer'; -import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from '@metaplex-foundation/mpl-token-metadata'; -import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from '@solana/spl-token'; +import { Buffer } from "node:buffer"; +import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata"; +import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from "@solana/spl-token"; import { Connection, Keypair, @@ -10,32 +10,33 @@ import { sendAndConfirmTransaction, Transaction, TransactionInstruction, -} from '@solana/web3.js'; -import { borshSerialize, CreateTokenArgsSchema, MintToArgsSchema, NftMinterInstruction } from './instructions'; +} from "@solana/web3.js"; +import { borshSerialize, CreateTokenArgsSchema, MintToArgsSchema, NftMinterInstruction } from "./instructions"; function createKeypairFromFile(path: string): Keypair { - return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require('node:fs').readFileSync(path, 'utf-8')))); + return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require("node:fs").readFileSync(path, "utf-8")))); } -describe('NFT Minter', async () => { +describe("NFT Minter", async () => { // const connection = new Connection(`http://localhost:8899`, 'confirmed'); - const connection = new Connection('https://api.devnet.solana.com/', 'confirmed'); - const payer = createKeypairFromFile(`${require('node:os').homedir()}/.config/solana/id.json`); - const program = createKeypairFromFile('./program/target/deploy/program-keypair.json'); + const connection = new Connection("https://api.devnet.solana.com/", "confirmed"); + const payer = createKeypairFromFile(`${require("node:os").homedir()}/.config/solana/id.json`); + const program = createKeypairFromFile("./program/target/deploy/program-keypair.json"); const mintKeypair: Keypair = Keypair.generate(); - it('Create an NFT!', async () => { + it("Create an NFT!", async () => { const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; const instructionData = borshSerialize(CreateTokenArgsSchema, { instruction: NftMinterInstruction.Create, - nft_title: 'Homer NFT', - nft_symbol: 'HOMR', - nft_uri: 'https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json', + nft_title: "Homer NFT", + nft_symbol: "HOMR", + nft_uri: + "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json", }); const ix = new TransactionInstruction({ @@ -59,19 +60,24 @@ describe('NFT Minter', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, mintKeypair]); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${mintKeypair.publicKey}`); console.log(` Tx Signature: ${sx}`); }); - it('Mint the NFT to your wallet!', async () => { + it("Mint the NFT to your wallet!", async () => { const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; const editionAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer(), Buffer.from('edition')], + [ + Buffer.from("metadata"), + TOKEN_METADATA_PROGRAM_ID.toBuffer(), + mintKeypair.publicKey.toBuffer(), + Buffer.from("edition"), + ], TOKEN_METADATA_PROGRAM_ID, )[0]; @@ -113,7 +119,7 @@ describe('NFT Minter', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]); - console.log('Success!'); + console.log("Success!"); console.log(` ATA Address: ${associatedTokenAccountAddress}`); console.log(` Tx Signature: ${sx}`); }); diff --git a/tokens/nft-operations/anchor/Anchor.toml b/tokens/nft-operations/anchor/Anchor.toml index 63d8c9a00..2cb03b630 100644 --- a/tokens/nft-operations/anchor/Anchor.toml +++ b/tokens/nft-operations/anchor/Anchor.toml @@ -2,23 +2,20 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false -[programs.localnet] -mint_nft = "3EMcczaGi9ivdLxvvFwRbGYeEUEHpGwabXegARw4jLxa" - [programs.devnet] mint_nft = "3EMcczaGi9ivdLxvvFwRbGYeEUEHpGwabXegARw4jLxa" -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +mint_nft = "Ezf9iNnBPVNr596tK59pTP1MdDWAS2VvNjyiK5gkbSEX" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -# Only run bankrun tests — the validator tests (mint-nft.ts) need Metaplex Token -# Metadata cloned from mainnet which is too slow/unreliable in CI. -# bankrun.test.ts uses a local fixture (tests/fixtures/token_metadata.so). -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/bankrun.test.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/nft-operations/anchor/Cargo.lock b/tokens/nft-operations/anchor/Cargo.lock index 239b185ee..77fb88dac 100644 --- a/tokens/nft-operations/anchor/Cargo.lock +++ b/tokens/nft-operations/anchor/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "generic-array", ] @@ -20,7 +20,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -38,13 +38,82 @@ dependencies = [ "zeroize", ] +[[package]] +name = "agave-feature-set" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e631ba26aeffe98dee3db0b8612fc7c67cda71bc57b0f82f28dc48231df6bc8" +dependencies = [ + "ahash", + "solana-epoch-schedule", + "solana-hash 3.1.0", + "solana-pubkey 3.0.0", + "solana-sha256-hasher", + "solana-svm-feature-set", +] + +[[package]] +name = "agave-reserved-account-keys" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d062865aedfbdc7511726d47e472687db0db4fb08e3c3ab2ac68570106c2f1b6" +dependencies = [ + "agave-feature-set", + "solana-pubkey 3.0.0", + "solana-sdk-ids", +] + +[[package]] +name = "agave-syscalls" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c89f228e93d1bc769578efd0c5a445715ae04ad96f9b6f8d16d018ad7f9221a" +dependencies = [ + "bincode", + "libsecp256k1", + "num-traits", + "solana-account", + "solana-account-info", + "solana-big-mod-exp", + "solana-blake3-hasher", + "solana-bn254", + "solana-clock", + "solana-cpi", + "solana-curve25519", + "solana-hash 3.1.0", + "solana-instruction", + "solana-keccak-hasher", + "solana-loader-v3-interface", + "solana-poseidon", + "solana-program-entrypoint", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sbpf", + "solana-sdk-ids", + "solana-secp256k1-recover", + "solana-sha256-hasher", + "solana-stable-layout", + "solana-stake-interface", + "solana-svm-callback", + "solana-svm-feature-set", + "solana-svm-log-collector", + "solana-svm-measure", + "solana-svm-timings", + "solana-svm-type-overrides", + "solana-sysvar", + "solana-sysvar-id", + "solana-transaction-context", + "thiserror 2.0.18", +] + [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -52,18 +121,24 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anchor-attribute-access-control" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3db7f5f8a6b16fa2b6e1b0222e656249c3abedf052e3943babf248929571204" +checksum = "b972f5fbd02524c92e4eb487c3c648904572702670f3d6fc81aef5f1751b1569" dependencies = [ "proc-macro2", "quote", @@ -72,9 +147,9 @@ dependencies = [ [[package]] name = "anchor-attribute-account" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a12661acaba9866a5f2d8d8d46a1eed8b484f41dc9f94f808c3b07d35726816" +checksum = "9acfcb07a92084bcfa9f6cc49a5c2e8e0e986f25f4b7caa184b7a2c9c9e561c2" dependencies = [ "anchor-syn", "proc-macro2", @@ -84,9 +159,9 @@ dependencies = [ [[package]] name = "anchor-attribute-constant" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dff08bc0187aafc559da8f63b5adeab0bcdf97128765c72dd9a4861f70627fc" +checksum = "8f46cc38f819377f07663b8eb492a701427950065e79d2d7b622a782443deb7a" dependencies = [ "anchor-syn", "quote", @@ -95,9 +170,9 @@ dependencies = [ [[package]] name = "anchor-attribute-error" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2af8ce12fb8cf782a3e127d376698a4548a518e38b4686f9c439adce4730b48" +checksum = "9c34748789107c9838329e058ca7b253e67f37b39ceae5a0a6c8d99f5d1bf1fe" dependencies = [ "anchor-syn", "quote", @@ -106,9 +181,9 @@ dependencies = [ [[package]] name = "anchor-attribute-event" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338be5df076369b99585264aaa46c66229ead67568d61bd38c3ab0fa7a15e554" +checksum = "1a28a3e5eefa03d9c5ef02b2139198f652547d38dddafc9c5545152dfba54556" dependencies = [ "anchor-syn", "proc-macro2", @@ -118,9 +193,9 @@ dependencies = [ [[package]] name = "anchor-attribute-program" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5c4ec70cef4ef7e2d87b4e9c550f727a43d691d3d7f3e4d6b2e3bd530ae098d" +checksum = "dfaa03865053cb168bfc4debe5992be87f397aa027dd81b69a2e44f2e5bae1c5" dependencies = [ "anchor-lang-idl", "anchor-syn", @@ -133,9 +208,9 @@ dependencies = [ [[package]] name = "anchor-derive-accounts" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f610cb50e10e4c404cc774f20a4eb602b904f68ea04590f8b1eb22a1e28b33e5" +checksum = "eef330db08f9ceee45c18ef96b15b869883d280c0ab5c6ff5d2e2f6481da7911" dependencies = [ "anchor-syn", "quote", @@ -144,9 +219,9 @@ dependencies = [ [[package]] name = "anchor-derive-serde" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9ead49a9689493f8857a61dd1abf1d70eeeeb0683f8c1e09b015ab5bdd382d" +checksum = "e0e80ff4e3ddb8c85aafd37926335c28f820516311e7106e5b7482b42e798aaa" dependencies = [ "anchor-syn", "proc-macro-crate 3.5.0", @@ -157,9 +232,9 @@ dependencies = [ [[package]] name = "anchor-derive-space" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4d1372743444967347b60f9311d2ee54a630152fd1d6d805adebd7fcd72056" +checksum = "2672af0ef4dfd5f5b6199355867b580cd8b4048093ef5208dd2b441305c15b8b" dependencies = [ "proc-macro2", "quote", @@ -168,9 +243,9 @@ dependencies = [ [[package]] name = "anchor-lang" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254d0cb160ea5c4c6a8c2f847bbd0f384fef733ebc36ef8426ae95f1bfda5757" +checksum = "8de9dce227fa0c08be20fef008c5b04681e1e0a15cb396e9619a9a1f800ff6cd" dependencies = [ "anchor-attribute-access-control", "anchor-attribute-account", @@ -184,7 +259,7 @@ dependencies = [ "anchor-lang-idl", "base64 0.21.7", "bincode", - "borsh 1.5.7", + "borsh 1.6.1", "bytemuck", "const-crypto", "solana-account-info", @@ -205,7 +280,7 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-sdk-ids", "solana-stake-interface", - "solana-system-interface", + "solana-system-interface 2.0.0", "solana-sysvar", "solana-sysvar-id", "thiserror 1.0.69", @@ -223,7 +298,7 @@ dependencies = [ "regex", "serde", "serde_json", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -238,9 +313,9 @@ dependencies = [ [[package]] name = "anchor-spl" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3f1da81d6a7486339833833db9285f3771c1c368db418d481b5584a901cd675" +checksum = "300e2e8058e674e8d6ea7c72dfb8be4349609dd9c3760ce729fc6406199624fe" dependencies = [ "anchor-lang", "mpl-token-metadata", @@ -255,9 +330,9 @@ dependencies = [ [[package]] name = "anchor-syn" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a855d34b1b0488f37ccc759c8bd4a696cd3a7bba8cb0734c2a965109f707da" +checksum = "c62f42cb7e348c033bd9bfba59979bcd66431c026ba23490af94045aa357a950" dependencies = [ "anyhow", "bs58", @@ -266,16 +341,266 @@ dependencies = [ "proc-macro2", "quote", "serde", - "sha2", + "sha2 0.10.9", "syn 1.0.109", "thiserror 1.0.69", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-std 0.4.0", +] + +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff 0.4.2", + "ark-poly 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.5", + "itertools 0.13.0", + "num-bigint 0.4.6", + "num-integer", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint 0.4.6", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint 0.4.6", + "num-traits", + "paste", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.5", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive 0.4.2", + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint 0.4.6", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "num-bigint 0.4.6", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ark-std" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", +] [[package]] name = "arrayref" @@ -285,15 +610,21 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ascii" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base16ct" @@ -301,6 +632,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + [[package]] name = "base64" version = "0.21.7" @@ -330,21 +667,32 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.4" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "blake3" -version = "1.8.2" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", + "cpufeatures 0.3.0", + "digest 0.11.2", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", ] [[package]] @@ -356,31 +704,41 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "borsh" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" dependencies = [ - "borsh-derive 0.10.3", + "borsh-derive 0.10.4", "hashbrown 0.13.2", ] [[package]] name = "borsh" -version = "1.5.7" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ - "borsh-derive 1.5.7", + "borsh-derive 1.6.1", + "bytes", "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" +checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -391,9 +749,9 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.7" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", "proc-macro-crate 3.5.0", @@ -404,9 +762,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" +checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3" dependencies = [ "proc-macro2", "quote", @@ -415,9 +773,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4" dependencies = [ "proc-macro2", "quote", @@ -435,9 +793,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bv" @@ -451,9 +809,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" dependencies = [ "bytemuck_derive", ] @@ -475,6 +833,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + [[package]] name = "cargo_toml" version = "0.19.2" @@ -482,14 +846,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" dependencies = [ "serde", - "toml 0.8.14", + "toml 0.8.23", ] [[package]] name = "cc" -version = "1.2.41" +version = "1.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" dependencies = [ "find-msvc-tools", "shlex", @@ -497,9 +861,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -508,15 +872,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] -name = "cipher" -version = "0.4.4" +name = "cfg_eval" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" dependencies = [ - "crypto-common", - "inout", -] - + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common 0.1.7", + "inout", +] + +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", +] + [[package]] name = "const-crypto" version = "0.3.0" @@ -535,19 +929,34 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -555,22 +964,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +dependencies = [ + "hybrid-array", +] + [[package]] name = "ctr" version = "0.9.2" @@ -580,6 +998,15 @@ dependencies = [ "cipher", ] +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -587,11 +1014,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", - "digest", + "digest 0.10.7", "fiat-crypto", - "rand_core", + "rand_core 0.6.4", "rustc_version", "serde", "subtle", @@ -615,8 +1042,18 @@ version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -633,13 +1070,37 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + [[package]] name = "darling_macro" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core", + "darling_core 0.21.3", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", "quote", "syn 2.0.117", ] @@ -660,18 +1121,55 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "const-oid", - "crypto-common", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "digest" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.1", + "ctutils", +] + +[[package]] +name = "eager" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe71d579d1812060163dff96056261deb5bf6729b100fa2e36a68b9649ba3d3" + [[package]] name = "ecdsa" version = "0.16.9" @@ -679,18 +1177,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest", + "digest 0.10.7", "elliptic-curve", "rfc6979", "signature", "spki", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.6.4", + "serde", + "sha2 0.10.9", + "subtle", + "zeroize", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" @@ -700,22 +1235,62 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest", + "digest 0.10.7", "ff", "generic-array", "group", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", ] +[[package]] +name = "enum-iterator" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd242f399be1da0a5354aa462d57b4ab2b4ee0683cc552f7c007d2d12d36e94" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "feature-probe" @@ -729,7 +1304,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -741,9 +1316,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "find-msvc-tools" -version = "0.1.4" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "five8" @@ -765,9 +1340,9 @@ dependencies = [ [[package]] name = "five8_core" -version = "0.1.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2551bf44bc5f776c15044b9b94153a00198be06743e262afaaa61f11ac7523a5" +checksum = "059c31d7d36c43fe39d89e55711858b4da8be7eb6dabac23c7289b1a19489406" [[package]] name = "fnv" @@ -788,17 +1363,40 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + [[package]] name = "group" version = "0.13.0" @@ -806,10 +1404,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.13.2" @@ -819,6 +1426,15 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", +] + [[package]] name = "hashbrown" version = "0.16.1" @@ -840,7 +1456,16 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", +] + +[[package]] +name = "hybrid-array" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +dependencies = [ + "typenum", ] [[package]] @@ -851,9 +1476,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -868,6 +1493,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -877,17 +1511,35 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ "once_cell", "wasm-bindgen", @@ -903,7 +1555,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "sha2", + "sha2 0.10.9", "signature", ] @@ -913,16 +1565,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f25ded719a2354f6b1a51d0c0741c25bc7afe038617664eb37f6418439eb084" dependencies = [ - "borsh 0.10.3", + "borsh 0.10.4", ] [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -939,68 +1591,206 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] -name = "lock_api" -version = "0.4.12" +name = "libsecp256k1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" dependencies = [ - "autocfg", - "scopeguard", + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", ] [[package]] -name = "log" -version = "0.4.28" +name = "libsecp256k1-core" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] [[package]] -name = "memchr" -version = "2.7.4" +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] [[package]] -name = "memoffset" -version = "0.9.1" +name = "libsecp256k1-gen-genmult" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" dependencies = [ - "autocfg", + "libsecp256k1-core", ] [[package]] -name = "merlin" -version = "3.0.0" +name = "light-poseidon" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" dependencies = [ - "byteorder", - "keccak", - "rand_core", - "zeroize", + "ark-bn254 0.4.0", + "ark-ff 0.4.2", + "num-bigint 0.4.6", + "thiserror 1.0.69", ] [[package]] -name = "mint-nft" -version = "0.1.0" +name = "light-poseidon" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47a1ccadd0bb5a32c196da536fd72c59183de24a055f6bf0513bf845fefab862" dependencies = [ - "anchor-lang", - "anchor-spl", + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "num-bigint 0.4.6", + "thiserror 1.0.69", ] [[package]] -name = "mpl-token-metadata" +name = "litesvm" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "347d8c652d592c618ac996f2ab21f8c0b0f2da3fbbca227a6887ee61bb75f2de" +dependencies = [ + "agave-feature-set", + "agave-reserved-account-keys", + "agave-syscalls", + "ansi_term", + "bincode", + "indexmap", + "itertools 0.14.0", + "log", + "serde", + "solana-account", + "solana-address 2.5.0", + "solana-address-lookup-table-interface", + "solana-bpf-loader-program", + "solana-builtins", + "solana-clock", + "solana-compute-budget", + "solana-compute-budget-instruction", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-feature-gate-interface", + "solana-fee", + "solana-fee-structure", + "solana-hash 3.1.0", + "solana-instruction", + "solana-instructions-sysvar", + "solana-keypair", + "solana-last-restart-slot", + "solana-loader-v3-interface", + "solana-loader-v4-interface", + "solana-message", + "solana-native-token", + "solana-nonce", + "solana-nonce-account", + "solana-precompile-error", + "solana-program-error", + "solana-program-runtime", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-sha256-hasher", + "solana-signature", + "solana-signer", + "solana-slot-hashes", + "solana-slot-history", + "solana-stake-interface", + "solana-svm-callback", + "solana-svm-log-collector", + "solana-svm-timings", + "solana-svm-transaction", + "solana-system-interface 2.0.0", + "solana-system-program", + "solana-sysvar", + "solana-sysvar-id", + "solana-transaction", + "solana-transaction-context", + "solana-transaction-error", + "thiserror 2.0.18", +] + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "mint-nft" +version = "0.1.0" +dependencies = [ + "anchor-lang", + "anchor-spl", + "borsh 1.6.1", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", +] + +[[package]] +name = "mpl-token-metadata" version = "5.1.2-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9824d84a8e23b634256591ce2f05b3180f7be5fcd193d939c43764c804aac5ef" dependencies = [ - "borsh 1.5.7", + "borsh 1.6.1", "kaigan", "num-derive 0.3.3", "num-traits", @@ -1009,6 +1799,31 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "num" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +dependencies = [ + "num-bigint 0.2.6", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -1019,6 +1834,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -1050,6 +1875,29 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-bigint 0.2.6", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1083,9 +1931,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "opaque-debug" @@ -1095,9 +1943,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1105,17 +1953,23 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-link", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pastey" version = "0.2.1" @@ -1128,14 +1982,23 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "percentage" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "2fd23b938276f14057220b707937bcb42fa76dda7560e57a2da30cb52d557937" +dependencies = [ + "num", +] [[package]] name = "pkcs8" @@ -1154,16 +2017,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro-crate" @@ -1180,7 +2046,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.8+spec-1.1.0", + "toml_edit 0.25.10+spec-1.1.0", ] [[package]] @@ -1201,6 +2067,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "qualifier_attr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "quote" version = "1.0.45" @@ -1210,6 +2087,25 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -1217,8 +2113,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -1228,7 +2144,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -1237,23 +2172,41 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -1263,9 +2216,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -1274,9 +2227,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rfc6979" @@ -1288,26 +2241,26 @@ dependencies = [ "subtle", ] +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "scopeguard" @@ -1331,9 +2284,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" @@ -1345,13 +2298,23 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + [[package]] name = "serde_bytes" -version = "0.11.15" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -1376,35 +2339,70 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" +dependencies = [ + "serde_core", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" +dependencies = [ + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "sha2" -version = "0.10.8" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", ] [[package]] @@ -1419,7 +2417,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest", + "digest 0.10.7", "keccak", ] @@ -1435,15 +2433,33 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", - "rand_core", + "digest 0.10.7", + "rand_core 0.6.4", ] [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "solana-account" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efc0ed36decb689413b9da5d57f2be49eea5bebb3cf7897015167b0c4336e731" +dependencies = [ + "bincode", + "serde", + "serde_bytes", + "serde_derive", + "solana-account-info", + "solana-clock", + "solana-instruction-error", + "solana-pubkey 4.1.0", + "solana-sdk-ids", + "solana-sysvar", +] [[package]] name = "solana-account-info" @@ -1453,7 +2469,7 @@ checksum = "a9cf16495d9eb53e3d04e72366a33bb1c20c24e78c171d8b8f5978357b63ae95" dependencies = [ "bincode", "serde_core", - "solana-address 2.4.0", + "solana-address 2.5.0", "solana-program-error", "solana-program-memory", ] @@ -1464,16 +2480,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2ecac8e1b7f74c2baa9e774c42817e3e75b20787134b76cc4d45e8a604488f5" dependencies = [ - "solana-address 2.4.0", + "solana-address 2.5.0", ] [[package]] name = "solana-address" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f67735365edc7fb19ed74ec950597107c8ee9cbfebac57b8868b3e78fb6df16" +checksum = "5f08236dacd0e6dc8234becef58e27c8567856644ef509d7e97957d55a91dc72" dependencies = [ - "borsh 1.5.7", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "curve25519-dalek", @@ -1497,8 +2513,14 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e8df0b083c10ce32490410f3795016b1b5d9b4d094658c0a5e496753645b7cd" dependencies = [ + "bincode", + "bytemuck", + "serde", + "serde_derive", "solana-clock", - "solana-pubkey 4.1.0", + "solana-instruction", + "solana-instruction-error", + "solana-pubkey 4.1.0", "solana-sdk-ids", "solana-slot-hashes", ] @@ -1518,11 +2540,22 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30c80fb6d791b3925d5ec4bf23a7c169ef5090c013059ec3ed7d0b2c04efa085" dependencies = [ - "num-bigint", + "num-bigint 0.4.6", "num-traits", "solana-define-syscall 3.0.0", ] +[[package]] +name = "solana-bincode" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278a1a5bad62cd9da89ac8d4b7ec444e83caa8ae96aa656dfc27684b28d49a5d" +dependencies = [ + "bincode", + "serde_core", + "solana-instruction-error", +] + [[package]] name = "solana-blake3-hasher" version = "3.1.0" @@ -1534,13 +2567,95 @@ dependencies = [ "solana-hash 4.2.0", ] +[[package]] +name = "solana-bn254" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ff13a8867fcc7b0f1114764e1bf6191b4551dcaf93729ddc676cd4ec6abc9f" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "bytemuck", + "solana-define-syscall 5.0.0", + "thiserror 2.0.18", +] + [[package]] name = "solana-borsh" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c04abbae16f57178a163125805637b8a076175bb5c0002fb04f4792bea901cf7" dependencies = [ - "borsh 1.5.7", + "borsh 1.6.1", +] + +[[package]] +name = "solana-bpf-loader-program" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe15f3c804c37fbff5971d34d81d5d2853ae2d03f11947f44f1d10c5b84c9df0" +dependencies = [ + "agave-syscalls", + "bincode", + "qualifier_attr", + "solana-account", + "solana-bincode", + "solana-clock", + "solana-instruction", + "solana-loader-v3-interface", + "solana-loader-v4-interface", + "solana-packet", + "solana-program-entrypoint", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sbpf", + "solana-sdk-ids", + "solana-svm-feature-set", + "solana-svm-log-collector", + "solana-svm-measure", + "solana-svm-type-overrides", + "solana-system-interface 2.0.0", + "solana-transaction-context", +] + +[[package]] +name = "solana-builtins" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d196c19ba1caf61782eba5de053061f298f36d9f2aec57073e2cf27403a926d3" +dependencies = [ + "agave-feature-set", + "solana-bpf-loader-program", + "solana-compute-budget-program", + "solana-hash 3.1.0", + "solana-loader-v4-program", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-system-program", + "solana-vote-program", + "solana-zk-elgamal-proof-program", + "solana-zk-token-proof-program", +] + +[[package]] +name = "solana-builtins-default-costs" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0da4d19885c5ee02d942a9e13354a39ef3ff591ee31d55353070c204ae7b8fed" +dependencies = [ + "agave-feature-set", + "ahash", + "log", + "solana-bpf-loader-program", + "solana-compute-budget-program", + "solana-loader-v4-program", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-system-program", + "solana-vote-program", ] [[package]] @@ -1556,6 +2671,57 @@ dependencies = [ "solana-sysvar-id", ] +[[package]] +name = "solana-compute-budget" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98426b2f7788c089f4ab840347bff55901e65ceb5d76b850194f0802a733cd4e" +dependencies = [ + "solana-fee-structure", + "solana-program-runtime", +] + +[[package]] +name = "solana-compute-budget-instruction" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb3ea80152fc745fa95d9cd2fc019c3591cdc7598cb4d85a6acdea7a40938f0" +dependencies = [ + "agave-feature-set", + "log", + "solana-borsh", + "solana-builtins-default-costs", + "solana-compute-budget", + "solana-compute-budget-interface", + "solana-instruction", + "solana-packet", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-svm-transaction", + "solana-transaction-error", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-compute-budget-interface" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8292c436b269ad23cecc8b24f7da3ab07ca111661e25e00ce0e1d22771951ab9" +dependencies = [ + "borsh 1.6.1", + "solana-instruction", + "solana-sdk-ids", +] + +[[package]] +name = "solana-compute-budget-program" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688491544a91b94fcb17cffb5cc4dca4be93bc96460fa27325a404c24b584130" +dependencies = [ + "solana-program-runtime", +] + [[package]] name = "solana-cpi" version = "3.1.0" @@ -1667,7 +2833,7 @@ dependencies = [ "solana-nonce", "solana-pubkey 3.0.0", "solana-sdk-ids", - "solana-system-interface", + "solana-system-interface 2.0.0", "thiserror 2.0.18", ] @@ -1677,9 +2843,28 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75ca9b5cbb6f500f7fd73db5bd95640f71a83f04d6121a0e59a43b202dca2731" dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account", + "solana-account-info", + "solana-instruction", "solana-program-error", "solana-pubkey 4.1.0", + "solana-rent 4.1.0", "solana-sdk-ids", + "solana-system-interface 3.1.0", +] + +[[package]] +name = "solana-fee" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487e4ba57d889e2ecf94a0cac3a3f385fe26d17425aaef3514b79975af2b5d7f" +dependencies = [ + "agave-feature-set", + "solana-fee-structure", + "solana-svm-transaction", ] [[package]] @@ -1693,6 +2878,12 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-fee-structure" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2abdb1223eea8ec64136f39cb1ffcf257e00f915c957c35c0dd9e3f4e700b0" + [[package]] name = "solana-hash" version = "3.1.0" @@ -1708,7 +2899,7 @@ version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8064ea1d591ec791be95245058ca40f4f5345d390c200069d0f79bbf55bfae55" dependencies = [ - "borsh 1.5.7", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "five8", @@ -1726,7 +2917,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97881335fc698deb46c6571945969aae6d93a14e2fff792a368b4fac872f116" dependencies = [ "bincode", - "borsh 1.5.7", + "borsh 1.6.1", "serde", "serde_derive", "solana-define-syscall 5.0.0", @@ -1741,6 +2932,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d3d048edaaeef5a3dc8c01853e585539a74417e4c2d43a9e2c161270045b838" dependencies = [ "num-traits", + "serde", + "serde_derive", "solana-program-error", ] @@ -1786,6 +2979,39 @@ dependencies = [ "solana-hash 4.2.0", ] +[[package]] +name = "solana-keypair" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "263d614c12aa267a3278703175fd6440552ca61bc960b5a02a4482720c53438b" +dependencies = [ + "ed25519-dalek", + "five8", + "five8_core", + "rand 0.9.2", + "solana-address 2.5.0", + "solana-seed-phrase", + "solana-signature", + "solana-signer", +] + +[[package]] +name = "solana-kite" +version = "0.3.0" +dependencies = [ + "litesvm", + "solana-account", + "solana-instruction", + "solana-keypair", + "solana-message", + "solana-program", + "solana-pubkey 3.0.0", + "solana-signer", + "solana-transaction", + "spl-associated-token-account", + "spl-token", +] + [[package]] name = "solana-last-restart-slot" version = "3.0.0" @@ -1811,7 +3037,46 @@ dependencies = [ "solana-instruction", "solana-pubkey 3.0.0", "solana-sdk-ids", - "solana-system-interface", + "solana-system-interface 2.0.0", +] + +[[package]] +name = "solana-loader-v4-interface" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c948b33ff81fa89699911b207059e493defdba9647eaf18f23abdf3674e0fb" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-system-interface 2.0.0", +] + +[[package]] +name = "solana-loader-v4-program" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b79ecebf56ff8acf46d5c0d77a11e1cb9a0f8eeb6dd1a69d739f3bf8ea8570e" +dependencies = [ + "log", + "solana-account", + "solana-bincode", + "solana-bpf-loader-program", + "solana-instruction", + "solana-loader-v3-interface", + "solana-loader-v4-interface", + "solana-packet", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sbpf", + "solana-sdk-ids", + "solana-svm-log-collector", + "solana-svm-measure", + "solana-svm-type-overrides", + "solana-transaction-context", ] [[package]] @@ -1820,10 +3085,12 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0448b1fd891c5f46491e5dc7d9986385ba3c852c340db2911dd29faa01d2b08d" dependencies = [ + "bincode", + "blake3", "lazy_static", "serde", "serde_derive", - "solana-address 2.4.0", + "solana-address 2.5.0", "solana-hash 4.2.0", "solana-instruction", "solana-sanitize", @@ -1853,21 +3120,67 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbc469152a63284ef959b80c59cda015262a021da55d3b8fe42171d89c4b64f8" dependencies = [ + "serde", + "serde_derive", "solana-fee-calculator", "solana-hash 4.2.0", "solana-pubkey 4.1.0", "solana-sha256-hasher", ] +[[package]] +name = "solana-nonce-account" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "805fd25b29e5a1a0e6c3dd6320c9da80f275fbe4ff6e392617c303a2085c435e" +dependencies = [ + "solana-account", + "solana-hash 3.1.0", + "solana-nonce", + "solana-sdk-ids", +] + [[package]] name = "solana-nullable" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90429a75d69fdcb31952c3dea79f5f3c8157cfe88221e066103c9c237876073" +checksum = "da028344c595c7416769ff648d206de7962571291a4cea24c38a60b6f40d53bb" dependencies = [ "bytemuck", ] +[[package]] +name = "solana-packet" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edf2f25743c95229ac0fdc32f8f5893ef738dbf332c669e9861d33ddb0f469d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "solana-poseidon" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d213ef5dc664927b43725e9aae1f0848e06d556e7a5f2857f37af9dbf9856c" +dependencies = [ + "ark-bn254 0.4.0", + "ark-bn254 0.5.0", + "light-poseidon 0.2.0", + "light-poseidon 0.4.0", + "solana-define-syscall 3.0.0", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-precompile-error" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cafcd950de74c6c39d55dc8ca108bbb007799842ab370ef26cf45a34453c31e1" +dependencies = [ + "num-traits", +] + [[package]] name = "solana-program" version = "3.0.0" @@ -1901,7 +3214,7 @@ dependencies = [ "solana-program-option", "solana-program-pack", "solana-pubkey 3.0.0", - "solana-rent", + "solana-rent 3.1.0", "solana-sdk-ids", "solana-secp256k1-recover", "solana-serde-varint", @@ -1933,7 +3246,7 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f04fa578707b3612b095f0c8e19b66a1233f7c42ca8082fcb3b745afcc0add6" dependencies = [ - "borsh 1.5.7", + "borsh 1.6.1", "serde", "serde_derive", ] @@ -1962,6 +3275,51 @@ dependencies = [ "solana-program-error", ] +[[package]] +name = "solana-program-runtime" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527e07453b083fa814e35bb56b8aaddb34d20eeeadeb0d13c115780365355c88" +dependencies = [ + "base64 0.22.1", + "bincode", + "itertools 0.12.1", + "log", + "percentage", + "rand 0.8.5", + "serde", + "solana-account", + "solana-account-info", + "solana-clock", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-fee-structure", + "solana-hash 3.1.0", + "solana-instruction", + "solana-last-restart-slot", + "solana-loader-v3-interface", + "solana-program-entrypoint", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sbpf", + "solana-sdk-ids", + "solana-slot-hashes", + "solana-stable-layout", + "solana-stake-interface", + "solana-svm-callback", + "solana-svm-feature-set", + "solana-svm-log-collector", + "solana-svm-measure", + "solana-svm-timings", + "solana-svm-transaction", + "solana-svm-type-overrides", + "solana-system-interface 2.0.0", + "solana-sysvar", + "solana-sysvar-id", + "solana-transaction-context", + "thiserror 2.0.18", +] + [[package]] name = "solana-pubkey" version = "3.0.0" @@ -1977,7 +3335,7 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b06bd918d60111ee1f97de817113e2040ca0cedb740099ee8d646233f6b906c" dependencies = [ - "solana-address 2.4.0", + "solana-address 2.5.0", ] [[package]] @@ -1993,19 +3351,45 @@ dependencies = [ "solana-sysvar-id", ] +[[package]] +name = "solana-rent" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1771d726d4854f1818c750e14aff40b19d84720d0b1b6d53e50e8f16cb6bd62" +dependencies = [ + "solana-sdk-macro", +] + [[package]] name = "solana-sanitize" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf09694a0fc14e5ffb18f9b7b7c0f15ecb6eac5b5610bf76a1853459d19daf9" +[[package]] +name = "solana-sbpf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15b079e08471a9dbfe1e48b2c7439c85aa2a055cbd54eddd8bd257b0a7dbb29" +dependencies = [ + "byteorder", + "combine", + "hash32", + "libc", + "log", + "rand 0.8.5", + "rustc-demangle", + "thiserror 2.0.18", + "winapi", +] + [[package]] name = "solana-sdk-ids" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "def234c1956ff616d46c9dd953f251fa7096ddbaa6d52b165218de97882b7280" dependencies = [ - "solana-address 2.4.0", + "solana-address 2.5.0", ] [[package]] @@ -2048,7 +3432,7 @@ checksum = "dc905b200a95f2ea9146e43f2a7181e3aeb55de6bc12afb36462d00a3c7310de" dependencies = [ "hmac", "pbkdf2", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -2077,7 +3461,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db7dc3011ea4c0334aaaa7e7128cb390ecf546b28d412e9bf2064680f57f588f" dependencies = [ - "sha2", + "sha2 0.10.9", "solana-define-syscall 4.0.1", "solana-hash 4.2.0", ] @@ -2097,8 +3481,13 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "132a93134f1262aa832f1849b83bec6c9945669b866da18661a427943b9e801e" dependencies = [ + "ed25519-dalek", "five8", + "serde", + "serde-big-array", + "serde_derive", "solana-sanitize", + "wincode", ] [[package]] @@ -2152,105 +3541,384 @@ dependencies = [ name = "solana-stake-interface" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9bc26191b533f9a6e5a14cca05174119819ced680a80febff2f5051a713f0db" +checksum = "b9bc26191b533f9a6e5a14cca05174119819ced680a80febff2f5051a713f0db" +dependencies = [ + "num-traits", + "serde", + "serde_derive", + "solana-clock", + "solana-cpi", + "solana-instruction", + "solana-program-error", + "solana-pubkey 3.0.0", + "solana-system-interface 2.0.0", + "solana-sysvar", + "solana-sysvar-id", +] + +[[package]] +name = "solana-svm-callback" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c895f1add5c9ceff634f485554ddbcbceb88cba71b2f753c4caaba461690d2c6" +dependencies = [ + "solana-account", + "solana-clock", + "solana-precompile-error", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "solana-svm-feature-set" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5addc8fc7beb262aed2df0c34322a04a1b07b82d35fac0a34cd01f5263f7e971" + +[[package]] +name = "solana-svm-log-collector" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e985304ae8370c2b14c5c31c3e4dfdd18bc38ba806ee341655119430116c1f0" +dependencies = [ + "log", +] + +[[package]] +name = "solana-svm-measure" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bc239ef12213c45a4077799a154f340b290938973ad11dc4aaedee8fe39319" + +[[package]] +name = "solana-svm-timings" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7bc8099ec662531e751607c096a2b336502b592ddd2cf584ec8312fd499fa8" +dependencies = [ + "eager", + "enum-iterator", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "solana-svm-transaction" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29a9d25c729620fc70664e17d787a7804e52903da6fc94810e5dac7ca3217064" +dependencies = [ + "solana-hash 3.1.0", + "solana-message", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-signature", + "solana-transaction", +] + +[[package]] +name = "solana-svm-type-overrides" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5093201eaac4a41edcaab9fc0060712d5bce2d2a0ca6134d18e9bcac2b3739bc" +dependencies = [ + "rand 0.8.5", +] + +[[package]] +name = "solana-system-interface" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e1790547bfc3061f1ee68ea9d8dc6c973c02a163697b24263a8e9f2e6d4afa2" +dependencies = [ + "num-traits", + "serde", + "serde_derive", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "solana-system-interface" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a95a6f2e23ed861d6444ad4a6d6896c418d7d101b960787e65a8e33157cee81b" +dependencies = [ + "num-traits", + "serde", + "serde_derive", + "solana-address 2.5.0", + "solana-instruction", + "solana-msg", + "solana-program-error", +] + +[[package]] +name = "solana-system-program" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab198a979e1bfa90e5a481fd3cec77326660e182668a248020cbd427c0ea1b5f" +dependencies = [ + "bincode", + "log", + "serde", + "solana-account", + "solana-bincode", + "solana-fee-calculator", + "solana-instruction", + "solana-nonce", + "solana-nonce-account", + "solana-packet", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-svm-log-collector", + "solana-svm-type-overrides", + "solana-system-interface 2.0.0", + "solana-sysvar", + "solana-transaction-context", +] + +[[package]] +name = "solana-sysvar" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6690d3dd88f15c21edff68eb391ef8800df7a1f5cec84ee3e8d1abf05affdf74" +dependencies = [ + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "lazy_static", + "serde", + "serde_derive", + "solana-account-info", + "solana-clock", + "solana-define-syscall 4.0.1", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-fee-calculator", + "solana-hash 4.2.0", + "solana-instruction", + "solana-last-restart-slot", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-pubkey 4.1.0", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-slot-hashes", + "solana-slot-history", + "solana-sysvar-id", +] + +[[package]] +name = "solana-sysvar-id" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17358d1e9a13e5b9c2264d301102126cf11a47fd394cdf3dec174fe7bc96e1de" +dependencies = [ + "solana-address 2.5.0", + "solana-sdk-ids", +] + +[[package]] +name = "solana-transaction" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96697cff5075a028265324255efed226099f6d761ca67342b230d09f72cc48d2" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-address 2.5.0", + "solana-hash 4.2.0", + "solana-instruction", + "solana-instruction-error", + "solana-message", + "solana-sanitize", + "solana-sdk-ids", + "solana-short-vec", + "solana-signature", + "solana-signer", + "solana-transaction-error", +] + +[[package]] +name = "solana-transaction-context" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c4936df4b86a943ea6d552ca2c64fcc0d1a06dee2193cbf463eaedc372736d" +dependencies = [ + "bincode", + "serde", + "solana-account", + "solana-instruction", + "solana-instructions-sysvar", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sbpf", + "solana-sdk-ids", +] + +[[package]] +name = "solana-transaction-error" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8396904805b0b385b9de115a652fe80fd01e5b98ce0513f4fcd8184ada9bb792" +dependencies = [ + "serde", + "serde_derive", + "solana-instruction-error", + "solana-sanitize", +] + +[[package]] +name = "solana-vote-interface" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6e123e16bfdd7a81d71b4c4699e0b29580b619f4cd2ef5b6aae1eb85e8979f" dependencies = [ + "bincode", + "cfg_eval", + "num-derive 0.4.2", "num-traits", "serde", "serde_derive", + "serde_with", "solana-clock", - "solana-cpi", + "solana-hash 3.1.0", "solana-instruction", - "solana-program-error", + "solana-instruction-error", "solana-pubkey 3.0.0", - "solana-system-interface", - "solana-sysvar", - "solana-sysvar-id", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-serde-varint", + "solana-serialize-utils", + "solana-short-vec", + "solana-system-interface 2.0.0", ] [[package]] -name = "solana-system-interface" -version = "2.0.0" +name = "solana-vote-program" +version = "3.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e1790547bfc3061f1ee68ea9d8dc6c973c02a163697b24263a8e9f2e6d4afa2" +checksum = "55e2eab8557ff61ae2f58ebdb63aabf3579e04eb3dd07e8b4c4102704a137bae" dependencies = [ + "agave-feature-set", + "bincode", + "log", + "num-derive 0.4.2", "num-traits", "serde", - "serde_derive", + "solana-account", + "solana-bincode", + "solana-clock", + "solana-epoch-schedule", + "solana-hash 3.1.0", "solana-instruction", - "solana-msg", - "solana-program-error", + "solana-keypair", + "solana-packet", + "solana-program-runtime", "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-signer", + "solana-slot-hashes", + "solana-transaction", + "solana-transaction-context", + "solana-vote-interface", + "thiserror 2.0.18", ] [[package]] -name = "solana-sysvar" -version = "3.1.1" +name = "solana-zero-copy" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6690d3dd88f15c21edff68eb391ef8800df7a1f5cec84ee3e8d1abf05affdf74" +checksum = "94f52dd8f733a13f6a18e55de83cf97c4c3f5fdf27ea3830bcff0b35313efcc2" dependencies = [ - "base64 0.22.1", - "bincode", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", - "lazy_static", - "serde", - "serde_derive", - "solana-account-info", - "solana-clock", - "solana-define-syscall 4.0.1", - "solana-epoch-rewards", - "solana-epoch-schedule", - "solana-fee-calculator", - "solana-hash 4.2.0", - "solana-instruction", - "solana-last-restart-slot", - "solana-program-entrypoint", - "solana-program-error", - "solana-program-memory", - "solana-pubkey 4.1.0", - "solana-rent", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-slot-hashes", - "solana-slot-history", - "solana-sysvar-id", ] [[package]] -name = "solana-sysvar-id" -version = "3.1.0" +name = "solana-zk-elgamal-proof-program" +version = "3.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17358d1e9a13e5b9c2264d301102126cf11a47fd394cdf3dec174fe7bc96e1de" +checksum = "98ebd77845de672972a32c357d7a68f2cc16c1037cc0ebf550ebba167827c10c" dependencies = [ - "solana-address 2.4.0", + "agave-feature-set", + "bytemuck", + "num-derive 0.4.2", + "num-traits", + "solana-instruction", + "solana-program-runtime", "solana-sdk-ids", + "solana-svm-log-collector", + "solana-zk-sdk", ] [[package]] -name = "solana-transaction-error" -version = "3.1.0" +name = "solana-zk-sdk" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8396904805b0b385b9de115a652fe80fd01e5b98ce0513f4fcd8184ada9bb792" +checksum = "9602bcb1f7af15caef92b91132ec2347e1c51a72ecdbefdaefa3eac4b8711475" dependencies = [ - "solana-instruction-error", - "solana-sanitize", + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek", + "getrandom 0.2.17", + "itertools 0.12.1", + "js-sys", + "merlin", + "num-derive 0.4.2", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha3", + "solana-derivation-path", + "solana-instruction", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-seed-derivable", + "solana-seed-phrase", + "solana-signature", + "solana-signer", + "subtle", + "thiserror 2.0.18", + "wasm-bindgen", + "zeroize", ] [[package]] -name = "solana-zero-copy" -version = "1.0.0" +name = "solana-zk-token-proof-program" +version = "3.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f52dd8f733a13f6a18e55de83cf97c4c3f5fdf27ea3830bcff0b35313efcc2" +checksum = "2c13a05831857b4e3320d98cdd77a3f7b645566508d8f66a07c9168ac1e8bc68" dependencies = [ + "agave-feature-set", "bytemuck", - "bytemuck_derive", + "num-derive 0.4.2", + "num-traits", + "solana-instruction", + "solana-program-runtime", + "solana-sdk-ids", + "solana-svm-log-collector", + "solana-zk-token-sdk", ] [[package]] -name = "solana-zk-sdk" -version = "4.0.0" +name = "solana-zk-token-sdk" +version = "3.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9602bcb1f7af15caef92b91132ec2347e1c51a72ecdbefdaefa3eac4b8711475" +checksum = "cd8dab3f2df045b7bec3cb3e1cff0889ec46d776191c3a2af19a77ddd3c4c6fc" dependencies = [ "aes-gcm-siv", "base64 0.22.1", @@ -2258,17 +3926,15 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek", - "getrandom", - "itertools", - "js-sys", + "itertools 0.12.1", "merlin", "num-derive 0.4.2", "num-traits", - "rand", + "rand 0.8.5", "serde", - "serde_derive", "serde_json", "sha3", + "solana-curve25519", "solana-derivation-path", "solana-instruction", "solana-pubkey 3.0.0", @@ -2279,7 +3945,6 @@ dependencies = [ "solana-signer", "subtle", "thiserror 2.0.18", - "wasm-bindgen", "zeroize", ] @@ -2293,12 +3958,39 @@ dependencies = [ "der", ] +[[package]] +name = "spl-associated-token-account" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0242277e290c023de8826f504abcf9206b3cd4e18d9ace4ec59a698b2828e88b" +dependencies = [ + "borsh 1.6.1", + "num-derive 0.4.2", + "num-traits", + "solana-account-info", + "solana-cpi", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-system-interface 2.0.0", + "solana-sysvar", + "spl-associated-token-account-interface", + "spl-token-2022-interface", + "spl-token-interface", + "thiserror 2.0.18", +] + [[package]] name = "spl-associated-token-account-interface" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6433917b60441d68d99a17e121d9db0ea15a9a69c0e5afa34649cf5ba12612f" dependencies = [ + "borsh 1.6.1", "solana-instruction", "solana-pubkey 3.0.0", ] @@ -2328,24 +4020,24 @@ dependencies = [ [[package]] name = "spl-discriminator-syn" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f05593b7ca9eac7caca309720f2eafb96355e037e6d373b909a80fe7b69b9" +checksum = "5d1dbc82ab91422345b6df40a79e2b78c7bce1ebb366da323572dd60b7076b67" dependencies = [ "proc-macro2", "quote", - "sha2", + "sha2 0.10.9", "syn 2.0.117", "thiserror 1.0.69", ] [[package]] name = "spl-pod" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f3df240f67bea453d4bc5749761e45436d14b9457ed667e0300555d5c271f3" +checksum = "2f9c6e142cdf1e7e77f480053ec9f0ce989890768ddf91f619b50f39d1b456f5" dependencies = [ - "borsh 1.5.7", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "num-derive 0.4.2", @@ -2354,10 +4046,39 @@ dependencies = [ "solana-program-error", "solana-program-option", "solana-pubkey 3.0.0", + "solana-zero-copy", "solana-zk-sdk", "thiserror 2.0.18", ] +[[package]] +name = "spl-token" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878b0183d51fcd8a53e1604f4c13321894cf53227e6773c529b0d03d499a8dfd" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.4.2", + "num-traits", + "num_enum", + "solana-account-info", + "solana-cpi", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-program-option", + "solana-program-pack", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-sysvar", + "spl-token-interface", + "thiserror 2.0.18", +] + [[package]] name = "spl-token-2022-interface" version = "2.1.0" @@ -2427,7 +4148,7 @@ dependencies = [ "num-derive 0.4.2", "num-traits", "num_enum", - "solana-address 2.4.0", + "solana-address 2.5.0", "solana-instruction", "solana-nullable", "solana-program-error", @@ -2462,7 +4183,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c467c7c3bd056f8fe60119e7ec34ddd6f23052c2fa8f1f51999098063b72676" dependencies = [ - "borsh 1.5.7", + "borsh 1.6.1", "num-derive 0.4.2", "num-traits", "solana-borsh", @@ -2568,9 +4289,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -2592,85 +4313,92 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.14" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", - "toml_datetime 0.6.6", - "toml_edit 0.22.14", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_datetime" -version = "1.1.0+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", "serde_spanned", - "toml_datetime 0.6.6", - "winnow 0.6.13", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.25.8+spec-1.1.0" +version = "0.25.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16bff38f1d86c47f9ff0647e6838d7bb362522bdf44006c7068c2b1e606f1f3c" +checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" dependencies = [ "indexmap", - "toml_datetime 1.1.0+spec-1.1.0", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.0", + "winnow 1.0.1", ] [[package]] name = "toml_parser" -version = "1.1.0+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.0", + "winnow 1.0.1", ] +[[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.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "universal-hash" @@ -2678,10 +4406,19 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + [[package]] name = "uriparse" version = "0.6.4" @@ -2694,48 +4431,55 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] -name = "wasm-bindgen" -version = "0.2.104" +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" +name = "wasm-bindgen" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.117", + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2743,31 +4487,53 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn 2.0.117", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "wincode" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc91ddd8c932a38bbec58ed536d9e93ce9cd01b6af9b6de3c501132cf98ddec6" +checksum = "657690780ce23e6f66576a782ffd88eb353512381817029cc1d7a99154bb6d1f" dependencies = [ "pastey", "proc-macro2", @@ -2782,108 +4548,56 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fca057fc9a13dd19cdb64ef558635d43c42667c0afa1ae7915ea1fa66993fd1a" dependencies = [ - "darling", + "darling 0.21.3", "proc-macro2", "quote", "syn 2.0.117", ] [[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "winnow" -version = "0.6.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] [[package]] name = "winnow" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -2901,11 +4615,17 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", "syn 2.0.117", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/tokens/nft-operations/anchor/package.json b/tokens/nft-operations/anchor/package.json index d0d9862f2..c87ff64cd 100644 --- a/tokens/nft-operations/anchor/package.json +++ b/tokens/nft-operations/anchor/package.json @@ -1,29 +1,29 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check", - "postinstall": "zx prepare.mjs" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@metaplex-foundation/mpl-token-metadata": "^3.1.2", - "@metaplex-foundation/umi": "^0.9.0", - "@solana/spl-token": "^0.4.6", - "axios": "^1.6.7", - "node-fetch": "^3.3.2" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3", - "zx": "^8.1.4" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check", + "postinstall": "zx prepare.mjs" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@metaplex-foundation/mpl-token-metadata": "^3.1.2", + "@metaplex-foundation/umi": "^0.9.0", + "@solana/spl-token": "^0.4.6", + "axios": "^1.6.7", + "node-fetch": "^3.3.2" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3", + "zx": "^8.1.4" + } } diff --git a/tokens/nft-operations/anchor/pnpm-lock.yaml b/tokens/nft-operations/anchor/pnpm-lock.yaml index 9fa6868ba..a0aa3f928 100644 --- a/tokens/nft-operations/anchor/pnpm-lock.yaml +++ b/tokens/nft-operations/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@metaplex-foundation/mpl-token-metadata': specifier: ^3.1.2 version: 3.2.1(@metaplex-foundation/umi@0.9.2) @@ -63,18 +63,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.7': @@ -1075,16 +1075,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -1102,7 +1102,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.7': dependencies: diff --git a/tokens/nft-operations/anchor/prepare.mjs b/tokens/nft-operations/anchor/prepare.mjs index 7c5ec464b..fb6b26225 100644 --- a/tokens/nft-operations/anchor/prepare.mjs +++ b/tokens/nft-operations/anchor/prepare.mjs @@ -1,17 +1,17 @@ #!/usr/bin/env zx -import { mkdir, rm } from 'node:fs/promises'; -import { join } from 'node:path'; -import { $ } from 'zx'; +import { mkdir, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { $ } from "zx"; const programs = [ { - id: 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', - name: 'token_metadata.so', + id: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", + name: "token_metadata.so", }, ]; -const outputDir = 'tests/fixtures'; +const outputDir = "tests/fixtures"; const overwrite = true; try { diff --git a/tokens/nft-operations/anchor/programs/mint-nft/Cargo.toml b/tokens/nft-operations/anchor/programs/mint-nft/Cargo.toml index 225819092..07383549e 100644 --- a/tokens/nft-operations/anchor/programs/mint-nft/Cargo.toml +++ b/tokens/nft-operations/anchor/programs/mint-nft/Cargo.toml @@ -20,8 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = { version = "1.0.0-rc.5", features = ["metadata"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = { version = "1.0.0", features = ["metadata"] } + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/nft-operations/anchor/programs/mint-nft/src/lib.rs b/tokens/nft-operations/anchor/programs/mint-nft/src/lib.rs index 09164ee35..3d5b66764 100644 --- a/tokens/nft-operations/anchor/programs/mint-nft/src/lib.rs +++ b/tokens/nft-operations/anchor/programs/mint-nft/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("3EMcczaGi9ivdLxvvFwRbGYeEUEHpGwabXegARw4jLxa"); +declare_id!("Ezf9iNnBPVNr596tK59pTP1MdDWAS2VvNjyiK5gkbSEX"); pub mod contexts; diff --git a/tokens/nft-operations/anchor/programs/mint-nft/tests/test_nft_operations.rs b/tokens/nft-operations/anchor/programs/mint-nft/tests/test_nft_operations.rs new file mode 100644 index 000000000..d22fdcf3b --- /dev/null +++ b/tokens/nft-operations/anchor/programs/mint-nft/tests/test_nft_operations.rs @@ -0,0 +1,332 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{ + create_wallet, get_token_account_balance, send_transaction_from_instructions, + }, + solana_signer::Signer, +}; + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn ata_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn metadata_program_id() -> Pubkey { + "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + .parse() + .unwrap() +} + +fn instructions_sysvar_id() -> Pubkey { + "Sysvar1nstructions1111111111111111111111111" + .parse() + .unwrap() +} + +fn derive_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey { + let (ata, _bump) = Pubkey::find_program_address( + &[wallet.as_ref(), token_program_id().as_ref(), mint.as_ref()], + &ata_program_id(), + ); + ata +} + +fn derive_metadata_pda(mint: &Pubkey) -> Pubkey { + let metadata_pid = metadata_program_id(); + let (pda, _bump) = Pubkey::find_program_address( + &[b"metadata", metadata_pid.as_ref(), mint.as_ref()], + &metadata_pid, + ); + pda +} + +fn derive_edition_pda(mint: &Pubkey) -> Pubkey { + let metadata_pid = metadata_program_id(); + let (pda, _bump) = Pubkey::find_program_address( + &[ + b"metadata", + metadata_pid.as_ref(), + mint.as_ref(), + b"edition", + ], + &metadata_pid, + ); + pda +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = mint_nft::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/mint_nft.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let metadata_bytes = include_bytes!("../../../tests/fixtures/mpl_token_metadata.so"); + svm.add_program(metadata_program_id(), metadata_bytes) + .unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_create_collection() { + let (mut svm, program_id, payer) = setup(); + let collection_keypair = Keypair::new(); + + let (mint_authority, _) = Pubkey::find_program_address(&[b"authority"], &program_id); + + let metadata = derive_metadata_pda(&collection_keypair.pubkey()); + let master_edition = derive_edition_pda(&collection_keypair.pubkey()); + let destination = derive_ata(&payer.pubkey(), &collection_keypair.pubkey()); + + let instruction = Instruction::new_with_bytes( + program_id, + &mint_nft::instruction::CreateCollection {}.data(), + mint_nft::accounts::CreateCollection { + user: payer.pubkey(), + mint: collection_keypair.pubkey(), + mint_authority, + metadata, + master_edition, + destination, + system_program: system_program::id(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + token_metadata_program: metadata_program_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![instruction], + &[&payer, &collection_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Verify collection mint exists + let mint_account = svm + .get_account(&collection_keypair.pubkey()) + .expect("Collection mint should exist"); + assert!(!mint_account.data.is_empty()); + + // Verify metadata exists + let meta_account = svm + .get_account(&metadata) + .expect("Metadata should exist"); + assert!(!meta_account.data.is_empty()); + + // Verify master edition exists + let edition_account = svm + .get_account(&master_edition) + .expect("Master edition should exist"); + assert!(!edition_account.data.is_empty()); + + // Verify 1 token was minted to destination + let balance = get_token_account_balance(&svm, &destination).unwrap(); + assert_eq!(balance, 1, "Should have 1 collection token"); +} + +#[test] +fn test_mint_nft_to_collection() { + let (mut svm, program_id, payer) = setup(); + + let (mint_authority, _) = Pubkey::find_program_address(&[b"authority"], &program_id); + + // Step 1: Create the collection + let collection_keypair = Keypair::new(); + let collection_metadata = derive_metadata_pda(&collection_keypair.pubkey()); + let collection_master_edition = derive_edition_pda(&collection_keypair.pubkey()); + let collection_destination = derive_ata(&payer.pubkey(), &collection_keypair.pubkey()); + + let create_collection_ix = Instruction::new_with_bytes( + program_id, + &mint_nft::instruction::CreateCollection {}.data(), + mint_nft::accounts::CreateCollection { + user: payer.pubkey(), + mint: collection_keypair.pubkey(), + mint_authority, + metadata: collection_metadata, + master_edition: collection_master_edition, + destination: collection_destination, + system_program: system_program::id(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + token_metadata_program: metadata_program_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![create_collection_ix], + &[&payer, &collection_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Step 2: Mint an NFT into the collection + svm.expire_blockhash(); + let nft_keypair = Keypair::new(); + let nft_metadata = derive_metadata_pda(&nft_keypair.pubkey()); + let nft_master_edition = derive_edition_pda(&nft_keypair.pubkey()); + let nft_destination = derive_ata(&payer.pubkey(), &nft_keypair.pubkey()); + + let mint_nft_ix = Instruction::new_with_bytes( + program_id, + &mint_nft::instruction::MintNft {}.data(), + mint_nft::accounts::MintNFT { + owner: payer.pubkey(), + mint: nft_keypair.pubkey(), + destination: nft_destination, + metadata: nft_metadata, + master_edition: nft_master_edition, + mint_authority, + collection_mint: collection_keypair.pubkey(), + system_program: system_program::id(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + token_metadata_program: metadata_program_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![mint_nft_ix], + &[&payer, &nft_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Verify NFT was minted + let balance = get_token_account_balance(&svm, &nft_destination).unwrap(); + assert_eq!(balance, 1, "Should have 1 NFT"); + + // Verify NFT metadata exists + let nft_meta = svm + .get_account(&nft_metadata) + .expect("NFT metadata should exist"); + assert!(!nft_meta.data.is_empty()); +} + +#[test] +fn test_verify_collection() { + let (mut svm, program_id, payer) = setup(); + + let (mint_authority, _) = Pubkey::find_program_address(&[b"authority"], &program_id); + + // Step 1: Create collection + let collection_keypair = Keypair::new(); + let collection_metadata = derive_metadata_pda(&collection_keypair.pubkey()); + let collection_master_edition = derive_edition_pda(&collection_keypair.pubkey()); + let collection_destination = derive_ata(&payer.pubkey(), &collection_keypair.pubkey()); + + let create_collection_ix = Instruction::new_with_bytes( + program_id, + &mint_nft::instruction::CreateCollection {}.data(), + mint_nft::accounts::CreateCollection { + user: payer.pubkey(), + mint: collection_keypair.pubkey(), + mint_authority, + metadata: collection_metadata, + master_edition: collection_master_edition, + destination: collection_destination, + system_program: system_program::id(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + token_metadata_program: metadata_program_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![create_collection_ix], + &[&payer, &collection_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Step 2: Mint NFT + svm.expire_blockhash(); + let nft_keypair = Keypair::new(); + let nft_metadata = derive_metadata_pda(&nft_keypair.pubkey()); + let nft_master_edition = derive_edition_pda(&nft_keypair.pubkey()); + let nft_destination = derive_ata(&payer.pubkey(), &nft_keypair.pubkey()); + + let mint_nft_ix = Instruction::new_with_bytes( + program_id, + &mint_nft::instruction::MintNft {}.data(), + mint_nft::accounts::MintNFT { + owner: payer.pubkey(), + mint: nft_keypair.pubkey(), + destination: nft_destination, + metadata: nft_metadata, + master_edition: nft_master_edition, + mint_authority, + collection_mint: collection_keypair.pubkey(), + system_program: system_program::id(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + token_metadata_program: metadata_program_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![mint_nft_ix], + &[&payer, &nft_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Step 3: Verify collection + svm.expire_blockhash(); + let verify_ix = Instruction::new_with_bytes( + program_id, + &mint_nft::instruction::VerifyCollection {}.data(), + mint_nft::accounts::VerifyCollectionMint { + authority: payer.pubkey(), + metadata: nft_metadata, + mint: nft_keypair.pubkey(), + mint_authority, + collection_mint: collection_keypair.pubkey(), + collection_metadata, + collection_master_edition, + system_program: system_program::id(), + sysvar_instruction: instructions_sysvar_id(), + token_metadata_program: metadata_program_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![verify_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); + + // Verify the metadata still exists after verification + let nft_meta = svm + .get_account(&nft_metadata) + .expect("NFT metadata should still exist after verification"); + assert!(!nft_meta.data.is_empty()); +} diff --git a/tokens/nft-operations/anchor/tests/bankrun.test.ts b/tokens/nft-operations/anchor/tests/bankrun.test.ts index 4babd06d9..b48ab0d3e 100644 --- a/tokens/nft-operations/anchor/tests/bankrun.test.ts +++ b/tokens/nft-operations/anchor/tests/bankrun.test.ts @@ -1,10 +1,6 @@ import * as anchor from "@anchor-lang/core"; import { ASSOCIATED_PROGRAM_ID } from "@anchor-lang/core/dist/cjs/utils/token"; -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - getAssociatedTokenAddressSync, -} from "@solana/spl-token"; +import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID } from "@solana/spl-token"; import { Keypair, PublicKey, SystemProgram } from "@solana/web3.js"; import { BankrunProvider } from "anchor-bankrun"; import { startAnchor } from "solana-bankrun"; @@ -12,166 +8,140 @@ import type { MintNft } from "../target/types/mint_nft"; const IDL = require("../target/idl/mint_nft.json"); const PROGRAM_ID = new PublicKey(IDL.address); -const METADATA_PROGRAM_ID = new PublicKey( - "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", -); +const METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); describe("mint-nft bankrun", async () => { - const context = await startAnchor( - "", - [ - { name: "mint_nft", programId: PROGRAM_ID }, - { name: "token_metadata", programId: METADATA_PROGRAM_ID }, - ], - [], - ); - const provider = new BankrunProvider(context); - anchor.setProvider(provider); - const wallet = provider.wallet as anchor.Wallet; - const program = new anchor.Program(IDL, provider); - - const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey( - "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", - ); - - const mintAuthority = anchor.web3.PublicKey.findProgramAddressSync( - [Buffer.from("authority")], - program.programId, - )[0]; - - const collectionKeypair = Keypair.generate(); - const collectionMint = collectionKeypair.publicKey; - - const mintKeypair = Keypair.generate(); - const mint = mintKeypair.publicKey; - - const getMetadata = async ( - mint: anchor.web3.PublicKey, - ): Promise => { - return anchor.web3.PublicKey.findProgramAddressSync( - [ - Buffer.from("metadata"), - TOKEN_METADATA_PROGRAM_ID.toBuffer(), - mint.toBuffer(), - ], - TOKEN_METADATA_PROGRAM_ID, - )[0]; - }; - - const getMasterEdition = async ( - mint: anchor.web3.PublicKey, - ): Promise => { - return anchor.web3.PublicKey.findProgramAddressSync( - [ - Buffer.from("metadata"), - TOKEN_METADATA_PROGRAM_ID.toBuffer(), - mint.toBuffer(), - Buffer.from("edition"), - ], - TOKEN_METADATA_PROGRAM_ID, - )[0]; - }; - - it("Create Collection NFT", async () => { - console.log("\nCollection Mint Key: ", collectionMint.toBase58()); - - const metadata = await getMetadata(collectionMint); - console.log("Collection Metadata Account: ", metadata.toBase58()); - - const masterEdition = await getMasterEdition(collectionMint); - console.log("Master Edition Account: ", masterEdition.toBase58()); - - const destination = getAssociatedTokenAddressSync( - collectionMint, - wallet.publicKey, - ); - console.log("Destination ATA = ", destination.toBase58()); - - const tx = await program.methods - .createCollection() - .accountsPartial({ - user: wallet.publicKey, - mint: collectionMint, - mintAuthority, - metadata, - masterEdition, - destination, - systemProgram: SystemProgram.programId, - tokenProgram: TOKEN_PROGRAM_ID, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, - }) - .signers([collectionKeypair]) - .rpc({ - skipPreflight: true, - }); - console.log("\nCollection NFT minted: TxID - ", tx); - }); - - it("Mint NFT", async () => { - console.log("\nMint", mint.toBase58()); - - const metadata = await getMetadata(mint); - console.log("Metadata", metadata.toBase58()); - - const masterEdition = await getMasterEdition(mint); - console.log("Master Edition", masterEdition.toBase58()); - - const destination = getAssociatedTokenAddressSync(mint, wallet.publicKey); - console.log("Destination", destination.toBase58()); - - const tx = await program.methods - .mintNft() - .accountsPartial({ - owner: wallet.publicKey, - destination, - metadata, - masterEdition, - mint, - mintAuthority, - collectionMint, - systemProgram: SystemProgram.programId, - tokenProgram: TOKEN_PROGRAM_ID, - associatedTokenProgram: ASSOCIATED_PROGRAM_ID, - tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, - }) - .signers([mintKeypair]) - .rpc({ - skipPreflight: true, - }); - console.log("\nNFT Minted! Your transaction signature", tx); - }); - - it("Verify Collection", async () => { - const mintMetadata = await getMetadata(mint); - console.log("\nMint Metadata", mintMetadata.toBase58()); - - const collectionMetadata = await getMetadata(collectionMint); - console.log("Collection Metadata", collectionMetadata.toBase58()); - - const collectionMasterEdition = await getMasterEdition(collectionMint); - console.log( - "Collection Master Edition", - collectionMasterEdition.toBase58(), - ); - - const tx = await program.methods - .verifyCollection() - .accountsPartial({ - authority: wallet.publicKey, - metadata: mintMetadata, - mint, - mintAuthority, - collectionMint, - collectionMetadata, - collectionMasterEdition, - systemProgram: SystemProgram.programId, - sysvarInstruction: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY, - tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, - }) - .rpc({ - skipPreflight: true, - }); - console.log("\nCollection Verified! Your transaction signature", tx); - }); + const context = await startAnchor( + "", + [ + { name: "mint_nft", programId: PROGRAM_ID }, + { name: "token_metadata", programId: METADATA_PROGRAM_ID }, + ], + [], + ); + const provider = new BankrunProvider(context); + anchor.setProvider(provider); + const wallet = provider.wallet as anchor.Wallet; + const program = new anchor.Program(IDL, provider); + + const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); + + const mintAuthority = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from("authority")], program.programId)[0]; + + const collectionKeypair = Keypair.generate(); + const collectionMint = collectionKeypair.publicKey; + + const mintKeypair = Keypair.generate(); + const mint = mintKeypair.publicKey; + + const getMetadata = async (mint: anchor.web3.PublicKey): Promise => { + return anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], + TOKEN_METADATA_PROGRAM_ID, + )[0]; + }; + + const getMasterEdition = async (mint: anchor.web3.PublicKey): Promise => { + return anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer(), Buffer.from("edition")], + TOKEN_METADATA_PROGRAM_ID, + )[0]; + }; + + it("Create Collection NFT", async () => { + console.log("\nCollection Mint Key: ", collectionMint.toBase58()); + + const metadata = await getMetadata(collectionMint); + console.log("Collection Metadata Account: ", metadata.toBase58()); + + const masterEdition = await getMasterEdition(collectionMint); + console.log("Master Edition Account: ", masterEdition.toBase58()); + + const destination = getAssociatedTokenAddressSync(collectionMint, wallet.publicKey); + console.log("Destination ATA = ", destination.toBase58()); + + const tx = await program.methods + .createCollection() + .accountsPartial({ + user: wallet.publicKey, + mint: collectionMint, + mintAuthority, + metadata, + masterEdition, + destination, + systemProgram: SystemProgram.programId, + tokenProgram: TOKEN_PROGRAM_ID, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, + }) + .signers([collectionKeypair]) + .rpc({ + skipPreflight: true, + }); + console.log("\nCollection NFT minted: TxID - ", tx); + }); + + it("Mint NFT", async () => { + console.log("\nMint", mint.toBase58()); + + const metadata = await getMetadata(mint); + console.log("Metadata", metadata.toBase58()); + + const masterEdition = await getMasterEdition(mint); + console.log("Master Edition", masterEdition.toBase58()); + + const destination = getAssociatedTokenAddressSync(mint, wallet.publicKey); + console.log("Destination", destination.toBase58()); + + const tx = await program.methods + .mintNft() + .accountsPartial({ + owner: wallet.publicKey, + destination, + metadata, + masterEdition, + mint, + mintAuthority, + collectionMint, + systemProgram: SystemProgram.programId, + tokenProgram: TOKEN_PROGRAM_ID, + associatedTokenProgram: ASSOCIATED_PROGRAM_ID, + tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, + }) + .signers([mintKeypair]) + .rpc({ + skipPreflight: true, + }); + console.log("\nNFT Minted! Your transaction signature", tx); + }); + + it("Verify Collection", async () => { + const mintMetadata = await getMetadata(mint); + console.log("\nMint Metadata", mintMetadata.toBase58()); + + const collectionMetadata = await getMetadata(collectionMint); + console.log("Collection Metadata", collectionMetadata.toBase58()); + + const collectionMasterEdition = await getMasterEdition(collectionMint); + console.log("Collection Master Edition", collectionMasterEdition.toBase58()); + + const tx = await program.methods + .verifyCollection() + .accountsPartial({ + authority: wallet.publicKey, + metadata: mintMetadata, + mint, + mintAuthority, + collectionMint, + collectionMetadata, + collectionMasterEdition, + systemProgram: SystemProgram.programId, + sysvarInstruction: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY, + tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, + }) + .rpc({ + skipPreflight: true, + }); + console.log("\nCollection Verified! Your transaction signature", tx); + }); }); diff --git a/tokens/nft-operations/anchor/tests/fixtures/mpl_token_metadata.so b/tokens/nft-operations/anchor/tests/fixtures/mpl_token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/nft-operations/anchor/tests/fixtures/mpl_token_metadata.so differ diff --git a/tokens/nft-operations/anchor/tests/fixtures/token_metadata.so b/tokens/nft-operations/anchor/tests/fixtures/token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/nft-operations/anchor/tests/fixtures/token_metadata.so differ diff --git a/tokens/nft-operations/anchor/tests/mint-nft.ts b/tokens/nft-operations/anchor/tests/mint-nft.ts index 198e93f70..e17981279 100644 --- a/tokens/nft-operations/anchor/tests/mint-nft.ts +++ b/tokens/nft-operations/anchor/tests/mint-nft.ts @@ -1,12 +1,12 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import type NodeWallet from '@anchor-lang/core/dist/cjs/nodewallet'; -import { ASSOCIATED_PROGRAM_ID } from '@anchor-lang/core/dist/cjs/utils/token'; -import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID } from '@solana/spl-token'; -import { Keypair, SystemProgram } from '@solana/web3.js'; -import type { MintNft } from '../target/types/mint_nft'; - -describe('mint-nft', () => { +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import type NodeWallet from "@anchor-lang/core/dist/cjs/nodewallet"; +import { ASSOCIATED_PROGRAM_ID } from "@anchor-lang/core/dist/cjs/utils/token"; +import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { Keypair, SystemProgram } from "@solana/web3.js"; +import type { MintNft } from "../target/types/mint_nft"; + +describe("mint-nft", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); @@ -15,9 +15,9 @@ describe('mint-nft', () => { const program = anchor.workspace.MintNft as Program; - const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'); + const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); - const mintAuthority = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from('authority')], program.programId)[0]; + const mintAuthority = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from("authority")], program.programId)[0]; const collectionKeypair = Keypair.generate(); const collectionMint = collectionKeypair.publicKey; @@ -27,29 +27,29 @@ describe('mint-nft', () => { const getMetadata = async (mint: anchor.web3.PublicKey): Promise => { return anchor.web3.PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; }; const getMasterEdition = async (mint: anchor.web3.PublicKey): Promise => { return anchor.web3.PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer(), Buffer.from('edition')], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer(), Buffer.from("edition")], TOKEN_METADATA_PROGRAM_ID, )[0]; }; - it('Create Collection NFT', async () => { - console.log('\nCollection Mint Key: ', collectionMint.toBase58()); + it("Create Collection NFT", async () => { + console.log("\nCollection Mint Key: ", collectionMint.toBase58()); const metadata = await getMetadata(collectionMint); - console.log('Collection Metadata Account: ', metadata.toBase58()); + console.log("Collection Metadata Account: ", metadata.toBase58()); const masterEdition = await getMasterEdition(collectionMint); - console.log('Master Edition Account: ', masterEdition.toBase58()); + console.log("Master Edition Account: ", masterEdition.toBase58()); const destination = getAssociatedTokenAddressSync(collectionMint, wallet.publicKey); - console.log('Destination ATA = ', destination.toBase58()); + console.log("Destination ATA = ", destination.toBase58()); const tx = await program.methods .createCollection() @@ -69,20 +69,20 @@ describe('mint-nft', () => { .rpc({ skipPreflight: true, }); - console.log('\nCollection NFT minted: TxID - ', tx); + console.log("\nCollection NFT minted: TxID - ", tx); }); - it('Mint NFT', async () => { - console.log('\nMint', mint.toBase58()); + it("Mint NFT", async () => { + console.log("\nMint", mint.toBase58()); const metadata = await getMetadata(mint); - console.log('Metadata', metadata.toBase58()); + console.log("Metadata", metadata.toBase58()); const masterEdition = await getMasterEdition(mint); - console.log('Master Edition', masterEdition.toBase58()); + console.log("Master Edition", masterEdition.toBase58()); const destination = getAssociatedTokenAddressSync(mint, wallet.publicKey); - console.log('Destination', destination.toBase58()); + console.log("Destination", destination.toBase58()); const tx = await program.methods .mintNft() @@ -103,18 +103,18 @@ describe('mint-nft', () => { .rpc({ skipPreflight: true, }); - console.log('\nNFT Minted! Your transaction signature', tx); + console.log("\nNFT Minted! Your transaction signature", tx); }); - it('Verify Collection', async () => { + it("Verify Collection", async () => { const mintMetadata = await getMetadata(mint); - console.log('\nMint Metadata', mintMetadata.toBase58()); + console.log("\nMint Metadata", mintMetadata.toBase58()); const collectionMetadata = await getMetadata(collectionMint); - console.log('Collection Metadata', collectionMetadata.toBase58()); + console.log("Collection Metadata", collectionMetadata.toBase58()); const collectionMasterEdition = await getMasterEdition(collectionMint); - console.log('Collection Master Edition', collectionMasterEdition.toBase58()); + console.log("Collection Master Edition", collectionMasterEdition.toBase58()); const tx = await program.methods .verifyCollection() @@ -133,6 +133,6 @@ describe('mint-nft', () => { .rpc({ skipPreflight: true, }); - console.log('\nCollection Verified! Your transaction signature', tx); + console.log("\nCollection Verified! Your transaction signature", tx); }); }); diff --git a/tokens/pda-mint-authority/anchor/Anchor.toml b/tokens/pda-mint-authority/anchor/Anchor.toml index 803ab7c40..3251fb3a1 100644 --- a/tokens/pda-mint-authority/anchor/Anchor.toml +++ b/tokens/pda-mint-authority/anchor/Anchor.toml @@ -6,16 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -token_minter = "3LFrPHqwk5jMrmiz48BFj6NV2k4NjobgTe1jChzx3JGD" - -# [registry] section removed — no longer used in Anchor 1.0 +token_minter = "3PMgRxk5r8i9ZFmaKPR55DGAKrBZncLSTqB4tpSxJjb5" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -# Only run bankrun tests — the validator tests (test.ts) need Metaplex Token -# Metadata cloned from mainnet which is too slow/unreliable in CI. -# bankrun.test.ts uses a local fixture (tests/fixtures/token_metadata.so). -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/bankrun.test.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/pda-mint-authority/anchor/package.json b/tokens/pda-mint-authority/anchor/package.json index 4042e17fa..bcc1cea1b 100644 --- a/tokens/pda-mint-authority/anchor/package.json +++ b/tokens/pda-mint-authority/anchor/package.json @@ -1,22 +1,22 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.3.8" - }, - "scripts": { - "postinstall": "zx prepare.mjs" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3", - "zx": "^8.1.4" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.3.8" + }, + "scripts": { + "postinstall": "zx prepare.mjs" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3", + "zx": "^8.1.4" + } } diff --git a/tokens/pda-mint-authority/anchor/pnpm-lock.yaml b/tokens/pda-mint-authority/anchor/pnpm-lock.yaml index 6c962e400..8858fc042 100644 --- a/tokens/pda-mint-authority/anchor/pnpm-lock.yaml +++ b/tokens/pda-mint-authority/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.3.8 version: 0.3.11(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -48,18 +48,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -840,16 +840,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -867,7 +867,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/pda-mint-authority/anchor/prepare.mjs b/tokens/pda-mint-authority/anchor/prepare.mjs index 7c5ec464b..fb6b26225 100644 --- a/tokens/pda-mint-authority/anchor/prepare.mjs +++ b/tokens/pda-mint-authority/anchor/prepare.mjs @@ -1,17 +1,17 @@ #!/usr/bin/env zx -import { mkdir, rm } from 'node:fs/promises'; -import { join } from 'node:path'; -import { $ } from 'zx'; +import { mkdir, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { $ } from "zx"; const programs = [ { - id: 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', - name: 'token_metadata.so', + id: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", + name: "token_metadata.so", }, ]; -const outputDir = 'tests/fixtures'; +const outputDir = "tests/fixtures"; const overwrite = true; try { diff --git a/tokens/pda-mint-authority/anchor/programs/token-minter/Cargo.toml b/tokens/pda-mint-authority/anchor/programs/token-minter/Cargo.toml index eed800f70..cd0690857 100644 --- a/tokens/pda-mint-authority/anchor/programs/token-minter/Cargo.toml +++ b/tokens/pda-mint-authority/anchor/programs/token-minter/Cargo.toml @@ -20,8 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = { version = "1.0.0-rc.5", features = ["metadata"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = { version = "1.0.0", features = ["metadata"] } + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/pda-mint-authority/anchor/programs/token-minter/src/lib.rs b/tokens/pda-mint-authority/anchor/programs/token-minter/src/lib.rs index 9d28f4ccc..b2b59922f 100644 --- a/tokens/pda-mint-authority/anchor/programs/token-minter/src/lib.rs +++ b/tokens/pda-mint-authority/anchor/programs/token-minter/src/lib.rs @@ -2,7 +2,7 @@ use anchor_lang::prelude::*; use instructions::*; pub mod instructions; -declare_id!("3LFrPHqwk5jMrmiz48BFj6NV2k4NjobgTe1jChzx3JGD"); +declare_id!("3PMgRxk5r8i9ZFmaKPR55DGAKrBZncLSTqB4tpSxJjb5"); #[program] pub mod token_minter { diff --git a/tokens/pda-mint-authority/anchor/programs/token-minter/tests/test_pda_mint.rs b/tokens/pda-mint-authority/anchor/programs/token-minter/tests/test_pda_mint.rs new file mode 100644 index 000000000..35f7ff18d --- /dev/null +++ b/tokens/pda-mint-authority/anchor/programs/token-minter/tests/test_pda_mint.rs @@ -0,0 +1,148 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{ + create_wallet, get_token_account_balance, send_transaction_from_instructions, + }, + solana_signer::Signer, +}; + +fn metadata_program_id() -> Pubkey { + "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + .parse() + .unwrap() +} + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn associated_token_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn rent_sysvar_id() -> Pubkey { + "SysvarRent111111111111111111111111111111111" + .parse() + .unwrap() +} + +fn derive_metadata_pda(mint: &Pubkey) -> Pubkey { + let metadata_pid = metadata_program_id(); + let (pda, _bump) = Pubkey::find_program_address( + &[b"metadata", metadata_pid.as_ref(), mint.as_ref()], + &metadata_pid, + ); + pda +} + +fn derive_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey { + let (ata, _bump) = Pubkey::find_program_address( + &[ + wallet.as_ref(), + token_program_id().as_ref(), + mint.as_ref(), + ], + &associated_token_program_id(), + ); + ata +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = token_minter::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/token_minter.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let metadata_bytes = include_bytes!("../../../tests/fixtures/mpl_token_metadata.so"); + svm.add_program(metadata_program_id(), metadata_bytes) + .unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_create_token_and_mint() { + let (mut svm, program_id, payer) = setup(); + + // Derive the PDA mint account (seeds = [b"mint"]) + let (mint_pda, _bump) = Pubkey::find_program_address(&[b"mint"], &program_id); + let metadata_account = derive_metadata_pda(&mint_pda); + + // 1. Create token + let create_ix = Instruction::new_with_bytes( + program_id, + &token_minter::instruction::CreateToken { + token_name: "Solana Gold".to_string(), + token_symbol: "GOLDSOL".to_string(), + token_uri: "https://example.com/token.json".to_string(), + } + .data(), + token_minter::accounts::CreateToken { + payer: payer.pubkey(), + mint_account: mint_pda, + metadata_account, + token_program: token_program_id(), + token_metadata_program: metadata_program_id(), + system_program: system_program::id(), + rent: rent_sysvar_id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![create_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); + + // Verify mint created + let mint_account = svm.get_account(&mint_pda).expect("Mint PDA should exist"); + assert!(!mint_account.data.is_empty()); + + // Verify metadata created + let meta = svm + .get_account(&metadata_account) + .expect("Metadata should exist"); + assert!(!meta.data.is_empty()); + + // 2. Mint tokens (100 tokens to payer's ATA) + svm.expire_blockhash(); + let ata = derive_ata(&payer.pubkey(), &mint_pda); + + let mint_ix = Instruction::new_with_bytes( + program_id, + &token_minter::instruction::MintToken { amount: 100 }.data(), + token_minter::accounts::MintToken { + payer: payer.pubkey(), + mint_account: mint_pda, + associated_token_account: ata, + token_program: token_program_id(), + associated_token_program: associated_token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![mint_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); + + // Verify: 100 * 10^9 = 100_000_000_000 tokens (9 decimals) + let balance = get_token_account_balance(&svm, &ata).unwrap(); + assert_eq!(balance, 100_000_000_000, "Should have 100 tokens"); +} diff --git a/tokens/pda-mint-authority/anchor/tests/bankrun.test.ts b/tokens/pda-mint-authority/anchor/tests/bankrun.test.ts index 7c4b0a991..2948ee994 100644 --- a/tokens/pda-mint-authority/anchor/tests/bankrun.test.ts +++ b/tokens/pda-mint-authority/anchor/tests/bankrun.test.ts @@ -4,76 +4,66 @@ import { PublicKey } from "@solana/web3.js"; import { BankrunProvider } from "anchor-bankrun"; import { BN } from "bn.js"; import { startAnchor } from "solana-bankrun"; +import IDL from "../target/idl/token_minter.json"; import type { TokenMinter } from "../target/types/token_minter"; -import IDL from "../target/idl/token_minter.json"; const PROGRAM_ID = new PublicKey(IDL.address); -const METADATA_PROGRAM_ID = new PublicKey( - "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", -); +const METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); describe("NFT Minter", async () => { - const context = await startAnchor( - "", - [ - { name: "token_minter", programId: PROGRAM_ID }, - { name: "token_metadata", programId: METADATA_PROGRAM_ID }, - ], - [], - ); - const provider = new BankrunProvider(context); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - const program = new anchor.Program(IDL, provider); + const context = await startAnchor( + "", + [ + { name: "token_minter", programId: PROGRAM_ID }, + { name: "token_metadata", programId: METADATA_PROGRAM_ID }, + ], + [], + ); + const provider = new BankrunProvider(context); + anchor.setProvider(provider); + const payer = provider.wallet as anchor.Wallet; + const program = new anchor.Program(IDL, provider); - // Derive the PDA to use as mint account address. - // This same PDA is also used as the mint authority. - const [mintPDA] = PublicKey.findProgramAddressSync( - [Buffer.from("mint")], - program.programId, - ); + // Derive the PDA to use as mint account address. + // This same PDA is also used as the mint authority. + const [mintPDA] = PublicKey.findProgramAddressSync([Buffer.from("mint")], program.programId); - const metadata = { - name: "Solana Gold", - symbol: "GOLDSOL", - uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", - }; + const metadata = { + name: "Solana Gold", + symbol: "GOLDSOL", + uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", + }; - it("Create a token!", async () => { - const transactionSignature = await program.methods - .createToken(metadata.name, metadata.symbol, metadata.uri) - .accounts({ - payer: payer.publicKey, - }) - .rpc(); + it("Create a token!", async () => { + const transactionSignature = await program.methods + .createToken(metadata.name, metadata.symbol, metadata.uri) + .accounts({ + payer: payer.publicKey, + }) + .rpc(); - console.log("Success!"); - console.log(` Mint Address: ${mintPDA}`); - console.log(` Transaction Signature: ${transactionSignature}`); - }); + console.log("Success!"); + console.log(` Mint Address: ${mintPDA}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); - it("Mint 1 Token!", async () => { - // Derive the associated token address account for the mint and payer. - const associatedTokenAccountAddress = getAssociatedTokenAddressSync( - mintPDA, - payer.publicKey, - ); + it("Mint 1 Token!", async () => { + // Derive the associated token address account for the mint and payer. + const associatedTokenAccountAddress = getAssociatedTokenAddressSync(mintPDA, payer.publicKey); - // Amount of tokens to mint. - const amount = new BN(100); + // Amount of tokens to mint. + const amount = new BN(100); - const transactionSignature = await program.methods - .mintToken(amount) - .accounts({ - payer: payer.publicKey, - associatedTokenAccount: associatedTokenAccountAddress, - }) - .rpc(); + const transactionSignature = await program.methods + .mintToken(amount) + .accounts({ + payer: payer.publicKey, + associatedTokenAccount: associatedTokenAccountAddress, + }) + .rpc(); - console.log("Success!"); - console.log( - ` Associated Token Account Address: ${associatedTokenAccountAddress}`, - ); - console.log(` Transaction Signature: ${transactionSignature}`); - }); + console.log("Success!"); + console.log(` Associated Token Account Address: ${associatedTokenAccountAddress}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); }); diff --git a/tokens/pda-mint-authority/anchor/tests/fixtures/mpl_token_metadata.so b/tokens/pda-mint-authority/anchor/tests/fixtures/mpl_token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/pda-mint-authority/anchor/tests/fixtures/mpl_token_metadata.so differ diff --git a/tokens/pda-mint-authority/anchor/tests/fixtures/token_metadata.so b/tokens/pda-mint-authority/anchor/tests/fixtures/token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/pda-mint-authority/anchor/tests/fixtures/token_metadata.so differ diff --git a/tokens/pda-mint-authority/anchor/tests/test.ts b/tokens/pda-mint-authority/anchor/tests/test.ts index 9371ebf86..a13a5b413 100644 --- a/tokens/pda-mint-authority/anchor/tests/test.ts +++ b/tokens/pda-mint-authority/anchor/tests/test.ts @@ -5,59 +5,51 @@ import { BN } from "bn.js"; import type { TokenMinter } from "../target/types/token_minter"; describe("NFT Minter", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - const program = anchor.workspace.TokenMinter as anchor.Program; - - // Derive the PDA to use as mint account address. - // This same PDA is also used as the mint authority. - const [mintPDA] = PublicKey.findProgramAddressSync( - [Buffer.from("mint")], - program.programId, - ); - - const metadata = { - name: "Solana Gold", - symbol: "GOLDSOL", - uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", - }; - - it("Create a token!", async () => { - const transactionSignature = await program.methods - .createToken(metadata.name, metadata.symbol, metadata.uri) - .accounts({ - payer: payer.publicKey, - }) - .rpc(); - - console.log("Success!"); - console.log(` Mint Address: ${mintPDA}`); - console.log(` Transaction Signature: ${transactionSignature}`); - }); - - it("Mint 1 Token!", async () => { - // Derive the associated token address account for the mint and payer. - const associatedTokenAccountAddress = getAssociatedTokenAddressSync( - mintPDA, - payer.publicKey, - ); - - // Amount of tokens to mint. - const amount = new BN(100); - - const transactionSignature = await program.methods - .mintToken(amount) - .accounts({ - payer: payer.publicKey, - associatedTokenAccount: associatedTokenAccountAddress, - }) - .rpc(); - - console.log("Success!"); - console.log( - ` Associated Token Account Address: ${associatedTokenAccountAddress}`, - ); - console.log(` Transaction Signature: ${transactionSignature}`); - }); + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const payer = provider.wallet as anchor.Wallet; + const program = anchor.workspace.TokenMinter as anchor.Program; + + // Derive the PDA to use as mint account address. + // This same PDA is also used as the mint authority. + const [mintPDA] = PublicKey.findProgramAddressSync([Buffer.from("mint")], program.programId); + + const metadata = { + name: "Solana Gold", + symbol: "GOLDSOL", + uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", + }; + + it("Create a token!", async () => { + const transactionSignature = await program.methods + .createToken(metadata.name, metadata.symbol, metadata.uri) + .accounts({ + payer: payer.publicKey, + }) + .rpc(); + + console.log("Success!"); + console.log(` Mint Address: ${mintPDA}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); + + it("Mint 1 Token!", async () => { + // Derive the associated token address account for the mint and payer. + const associatedTokenAccountAddress = getAssociatedTokenAddressSync(mintPDA, payer.publicKey); + + // Amount of tokens to mint. + const amount = new BN(100); + + const transactionSignature = await program.methods + .mintToken(amount) + .accounts({ + payer: payer.publicKey, + associatedTokenAccount: associatedTokenAccountAddress, + }) + .rpc(); + + console.log("Success!"); + console.log(` Associated Token Account Address: ${associatedTokenAccountAddress}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); }); diff --git a/tokens/pda-mint-authority/native/tests/instructions.ts b/tokens/pda-mint-authority/native/tests/instructions.ts index c06932ef9..0995c6c98 100644 --- a/tokens/pda-mint-authority/native/tests/instructions.ts +++ b/tokens/pda-mint-authority/native/tests/instructions.ts @@ -1,4 +1,4 @@ -import * as borsh from 'borsh'; +import * as borsh from "borsh"; export enum NftMinterInstruction { Init = 0, @@ -6,18 +6,18 @@ export enum NftMinterInstruction { Mint = 2, } -export const InitArgsSchema = { struct: { instruction: 'u8' } }; +export const InitArgsSchema = { struct: { instruction: "u8" } }; export const CreateTokenArgsSchema = { struct: { - instruction: 'u8', - nft_title: 'string', - nft_symbol: 'string', - nft_uri: 'string', + instruction: "u8", + nft_title: "string", + nft_symbol: "string", + nft_uri: "string", }, }; -export const MintToArgsSchema = { struct: { instruction: 'u8' } }; +export const MintToArgsSchema = { struct: { instruction: "u8" } }; export function borshSerialize(schema: borsh.Schema, data: object): Buffer { return Buffer.from(borsh.serialize(schema, data)); diff --git a/tokens/pda-mint-authority/native/tests/test.ts b/tokens/pda-mint-authority/native/tests/test.ts index 5528d3c11..65e31ee38 100644 --- a/tokens/pda-mint-authority/native/tests/test.ts +++ b/tokens/pda-mint-authority/native/tests/test.ts @@ -1,6 +1,6 @@ -import { Buffer } from 'node:buffer'; -import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from '@metaplex-foundation/mpl-token-metadata'; -import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from '@solana/spl-token'; +import { Buffer } from "node:buffer"; +import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata"; +import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from "@solana/spl-token"; import { Connection, Keypair, @@ -10,24 +10,33 @@ import { sendAndConfirmTransaction, Transaction, TransactionInstruction, -} from '@solana/web3.js'; -import { borshSerialize, InitArgsSchema, CreateTokenArgsSchema, MintToArgsSchema, NftMinterInstruction } from './instructions'; +} from "@solana/web3.js"; +import { + borshSerialize, + CreateTokenArgsSchema, + InitArgsSchema, + MintToArgsSchema, + NftMinterInstruction, +} from "./instructions"; function createKeypairFromFile(path: string): Keypair { - return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require('node:fs').readFileSync(path, 'utf-8')))); + return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require("node:fs").readFileSync(path, "utf-8")))); } -describe('NFT Minter', async () => { +describe("NFT Minter", async () => { // const connection = new Connection(`http://localhost:8899`, 'confirmed'); - const connection = new Connection('https://api.devnet.solana.com/', 'confirmed'); - const payer = createKeypairFromFile(`${require('node:os').homedir()}/.config/solana/id.json`); - const program = createKeypairFromFile('./program/target/deploy/program-keypair.json'); + const connection = new Connection("https://api.devnet.solana.com/", "confirmed"); + const payer = createKeypairFromFile(`${require("node:os").homedir()}/.config/solana/id.json`); + const program = createKeypairFromFile("./program/target/deploy/program-keypair.json"); - const mintAuthorityPublicKey = PublicKey.findProgramAddressSync([Buffer.from('mint_authority')], program.publicKey)[0]; + const mintAuthorityPublicKey = PublicKey.findProgramAddressSync( + [Buffer.from("mint_authority")], + program.publicKey, + )[0]; const mintKeypair: Keypair = Keypair.generate(); - it('Init Mint Authority PDA', async () => { + it("Init Mint Authority PDA", async () => { const instructionData = borshSerialize(InitArgsSchema, { instruction: NftMinterInstruction.Init, }); @@ -44,22 +53,23 @@ describe('NFT Minter', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer], { skipPreflight: true }); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${mintKeypair.publicKey}`); console.log(` Tx Signature: ${sx}`); }); - it('Create an NFT!', async () => { + it("Create an NFT!", async () => { const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; const instructionData = borshSerialize(CreateTokenArgsSchema, { instruction: NftMinterInstruction.Create, - nft_title: 'Homer NFT', - nft_symbol: 'HOMR', - nft_uri: 'https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json', + nft_title: "Homer NFT", + nft_symbol: "HOMR", + nft_uri: + "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json", }); const ix = new TransactionInstruction({ @@ -81,21 +91,28 @@ describe('NFT Minter', async () => { data: instructionData, }); - const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, mintKeypair], { skipPreflight: true }); + const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, mintKeypair], { + skipPreflight: true, + }); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${mintKeypair.publicKey}`); console.log(` Tx Signature: ${sx}`); }); - it('Mint the NFT to your wallet!', async () => { + it("Mint the NFT to your wallet!", async () => { const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; const editionAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer(), Buffer.from('edition')], + [ + Buffer.from("metadata"), + TOKEN_METADATA_PROGRAM_ID.toBuffer(), + mintKeypair.publicKey.toBuffer(), + Buffer.from("edition"), + ], TOKEN_METADATA_PROGRAM_ID, )[0]; @@ -137,7 +154,7 @@ describe('NFT Minter', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]); - console.log('Success!'); + console.log("Success!"); console.log(` ATA Address: ${associatedTokenAccountAddress}`); console.log(` Tx Signature: ${sx}`); }); diff --git a/tokens/spl-token-minter/anchor/Anchor.toml b/tokens/spl-token-minter/anchor/Anchor.toml index 85224170a..a4ce5be52 100644 --- a/tokens/spl-token-minter/anchor/Anchor.toml +++ b/tokens/spl-token-minter/anchor/Anchor.toml @@ -6,16 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -spl_token_minter = "3of89Z9jwek9zrFgpCWc9jZvQvitpVMxpZNsrAD2vQUD" - -# [registry] section removed — no longer used in Anchor 1.0 +spl_token_minter = "37nJupU7iBErqAjq5RTRRMvRbmkzngJRGBKG4yA2CxaH" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -# Only run bankrun tests — the validator tests (test.ts) need Metaplex Token -# Metadata cloned from mainnet which is too slow/unreliable in CI. -# bankrun.test.ts uses a local fixture (tests/fixtures/token_metadata.so). -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/bankrun.test.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/spl-token-minter/anchor/package.json b/tokens/spl-token-minter/anchor/package.json index 4042e17fa..bcc1cea1b 100644 --- a/tokens/spl-token-minter/anchor/package.json +++ b/tokens/spl-token-minter/anchor/package.json @@ -1,22 +1,22 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.3.8" - }, - "scripts": { - "postinstall": "zx prepare.mjs" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3", - "zx": "^8.1.4" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.3.8" + }, + "scripts": { + "postinstall": "zx prepare.mjs" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3", + "zx": "^8.1.4" + } } diff --git a/tokens/spl-token-minter/anchor/pnpm-lock.yaml b/tokens/spl-token-minter/anchor/pnpm-lock.yaml index 6c962e400..8858fc042 100644 --- a/tokens/spl-token-minter/anchor/pnpm-lock.yaml +++ b/tokens/spl-token-minter/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.3.8 version: 0.3.11(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -48,18 +48,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -840,16 +840,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -867,7 +867,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/spl-token-minter/anchor/prepare.mjs b/tokens/spl-token-minter/anchor/prepare.mjs index 7c5ec464b..fb6b26225 100644 --- a/tokens/spl-token-minter/anchor/prepare.mjs +++ b/tokens/spl-token-minter/anchor/prepare.mjs @@ -1,17 +1,17 @@ #!/usr/bin/env zx -import { mkdir, rm } from 'node:fs/promises'; -import { join } from 'node:path'; -import { $ } from 'zx'; +import { mkdir, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { $ } from "zx"; const programs = [ { - id: 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', - name: 'token_metadata.so', + id: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", + name: "token_metadata.so", }, ]; -const outputDir = 'tests/fixtures'; +const outputDir = "tests/fixtures"; const overwrite = true; try { diff --git a/tokens/spl-token-minter/anchor/programs/spl-token-minter/Cargo.toml b/tokens/spl-token-minter/anchor/programs/spl-token-minter/Cargo.toml index 2cbd907a1..9d602f735 100644 --- a/tokens/spl-token-minter/anchor/programs/spl-token-minter/Cargo.toml +++ b/tokens/spl-token-minter/anchor/programs/spl-token-minter/Cargo.toml @@ -20,8 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = { version = "1.0.0-rc.5", features = ["metadata"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = { version = "1.0.0", features = ["metadata"] } + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/spl-token-minter/anchor/programs/spl-token-minter/src/lib.rs b/tokens/spl-token-minter/anchor/programs/spl-token-minter/src/lib.rs index 56515e829..119e56617 100644 --- a/tokens/spl-token-minter/anchor/programs/spl-token-minter/src/lib.rs +++ b/tokens/spl-token-minter/anchor/programs/spl-token-minter/src/lib.rs @@ -3,7 +3,7 @@ use anchor_lang::prelude::*; pub mod instructions; use instructions::*; -declare_id!("3of89Z9jwek9zrFgpCWc9jZvQvitpVMxpZNsrAD2vQUD"); +declare_id!("37nJupU7iBErqAjq5RTRRMvRbmkzngJRGBKG4yA2CxaH"); #[program] pub mod spl_token_minter { diff --git a/tokens/spl-token-minter/anchor/programs/spl-token-minter/tests/test_spl_token_minter.rs b/tokens/spl-token-minter/anchor/programs/spl-token-minter/tests/test_spl_token_minter.rs new file mode 100644 index 000000000..a51678762 --- /dev/null +++ b/tokens/spl-token-minter/anchor/programs/spl-token-minter/tests/test_spl_token_minter.rs @@ -0,0 +1,183 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{ + create_wallet, get_token_account_balance, send_transaction_from_instructions, + }, + solana_signer::Signer, +}; + +fn metadata_program_id() -> Pubkey { + "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + .parse() + .unwrap() +} + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn associated_token_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn rent_sysvar_id() -> Pubkey { + "SysvarRent111111111111111111111111111111111" + .parse() + .unwrap() +} + +fn derive_metadata_pda(mint: &Pubkey) -> Pubkey { + let metadata_pid = metadata_program_id(); + let (pda, _bump) = Pubkey::find_program_address( + &[b"metadata", metadata_pid.as_ref(), mint.as_ref()], + &metadata_pid, + ); + pda +} + +fn derive_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey { + let (ata, _bump) = Pubkey::find_program_address( + &[ + wallet.as_ref(), + token_program_id().as_ref(), + mint.as_ref(), + ], + &associated_token_program_id(), + ); + ata +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = spl_token_minter::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/spl_token_minter.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let metadata_bytes = include_bytes!("../../../tests/fixtures/mpl_token_metadata.so"); + svm.add_program(metadata_program_id(), metadata_bytes) + .unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_create_token() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + let metadata_account = derive_metadata_pda(&mint_keypair.pubkey()); + + let create_ix = Instruction::new_with_bytes( + program_id, + &spl_token_minter::instruction::CreateToken { + token_name: "Solana Gold".to_string(), + token_symbol: "GOLDSOL".to_string(), + token_uri: "https://example.com/token.json".to_string(), + } + .data(), + spl_token_minter::accounts::CreateToken { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + metadata_account, + token_program: token_program_id(), + token_metadata_program: metadata_program_id(), + system_program: system_program::id(), + rent: rent_sysvar_id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![create_ix], + &[&payer, &mint_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Verify mint created + let mint = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint should exist"); + assert!(!mint.data.is_empty()); + + // Verify metadata created + let meta = svm + .get_account(&metadata_account) + .expect("Metadata should exist"); + assert!(!meta.data.is_empty()); +} + +#[test] +fn test_create_and_mint_tokens() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + let metadata_account = derive_metadata_pda(&mint_keypair.pubkey()); + + // 1. Create token + let create_ix = Instruction::new_with_bytes( + program_id, + &spl_token_minter::instruction::CreateToken { + token_name: "Solana Gold".to_string(), + token_symbol: "GOLDSOL".to_string(), + token_uri: "https://example.com/token.json".to_string(), + } + .data(), + spl_token_minter::accounts::CreateToken { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + metadata_account, + token_program: token_program_id(), + token_metadata_program: metadata_program_id(), + system_program: system_program::id(), + rent: rent_sysvar_id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![create_ix], + &[&payer, &mint_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // 2. Mint 100 tokens + svm.expire_blockhash(); + let ata = derive_ata(&payer.pubkey(), &mint_keypair.pubkey()); + + let mint_ix = Instruction::new_with_bytes( + program_id, + &spl_token_minter::instruction::MintToken { amount: 100 }.data(), + spl_token_minter::accounts::MintToken { + mint_authority: payer.pubkey(), + recipient: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + associated_token_account: ata, + token_program: token_program_id(), + associated_token_program: associated_token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![mint_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); + + // Verify: 100 * 10^9 = 100_000_000_000 tokens minted (9 decimals) + let balance = get_token_account_balance(&svm, &ata).unwrap(); + assert_eq!(balance, 100_000_000_000, "Should have 100 tokens"); +} diff --git a/tokens/spl-token-minter/anchor/tests/bankrun.test.ts b/tokens/spl-token-minter/anchor/tests/bankrun.test.ts index c740d1ddb..7c59e6eee 100644 --- a/tokens/spl-token-minter/anchor/tests/bankrun.test.ts +++ b/tokens/spl-token-minter/anchor/tests/bankrun.test.ts @@ -4,78 +4,71 @@ import { Keypair, PublicKey } from "@solana/web3.js"; import { BankrunProvider } from "anchor-bankrun"; import { BN } from "bn.js"; import { startAnchor } from "solana-bankrun"; +import IDL from "../target/idl/spl_token_minter.json"; import type { SplTokenMinter } from "../target/types/spl_token_minter"; -import IDL from "../target/idl/spl_token_minter.json"; const PROGRAM_ID = new PublicKey(IDL.address); -const METADATA_PROGRAM_ID = new PublicKey( - "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", -); +const METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); describe("SPL Token Minter", async () => { - const context = await startAnchor( - "", - [ - { name: "spl_token_minter", programId: PROGRAM_ID }, - { name: "token_metadata", programId: METADATA_PROGRAM_ID }, - ], - [], - ); + const context = await startAnchor( + "", + [ + { name: "spl_token_minter", programId: PROGRAM_ID }, + { name: "token_metadata", programId: METADATA_PROGRAM_ID }, + ], + [], + ); - const provider = new BankrunProvider(context); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - const program = new anchor.Program(IDL, provider); + const provider = new BankrunProvider(context); + anchor.setProvider(provider); + const payer = provider.wallet as anchor.Wallet; + const program = new anchor.Program(IDL, provider); - const metadata = { - name: "Solana Gold", - symbol: "GOLDSOL", - uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", - }; + const metadata = { + name: "Solana Gold", + symbol: "GOLDSOL", + uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", + }; - // Generate new keypair to use as address for mint account. - const mintKeypair = new Keypair(); + // Generate new keypair to use as address for mint account. + const mintKeypair = new Keypair(); - it("Create an SPL Token!", async () => { - const transactionSignature = await program.methods - .createToken(metadata.name, metadata.symbol, metadata.uri) - .accounts({ - payer: payer.publicKey, - mintAccount: mintKeypair.publicKey, - }) - .signers([mintKeypair]) - .rpc(); + it("Create an SPL Token!", async () => { + const transactionSignature = await program.methods + .createToken(metadata.name, metadata.symbol, metadata.uri) + .accounts({ + payer: payer.publicKey, + mintAccount: mintKeypair.publicKey, + }) + .signers([mintKeypair]) + .rpc(); - console.log("Success!"); - console.log(` Mint Address: ${mintKeypair.publicKey}`); - console.log(` Transaction Signature: ${transactionSignature}`); - }); + console.log("Success!"); + console.log(` Mint Address: ${mintKeypair.publicKey}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); - it("Mint some tokens to your wallet!", async () => { - // Derive the associated token address account for the mint and payer. - const associatedTokenAccountAddress = getAssociatedTokenAddressSync( - mintKeypair.publicKey, - payer.publicKey, - ); + it("Mint some tokens to your wallet!", async () => { + // Derive the associated token address account for the mint and payer. + const associatedTokenAccountAddress = getAssociatedTokenAddressSync(mintKeypair.publicKey, payer.publicKey); - // Amount of tokens to mint. - const amount = new BN(100); + // Amount of tokens to mint. + const amount = new BN(100); - // Mint the tokens to the associated token account. - const transactionSignature = await program.methods - .mintToken(amount) - .accounts({ - mintAuthority: payer.publicKey, - recipient: payer.publicKey, - mintAccount: mintKeypair.publicKey, - associatedTokenAccount: associatedTokenAccountAddress, - }) - .rpc(); + // Mint the tokens to the associated token account. + const transactionSignature = await program.methods + .mintToken(amount) + .accounts({ + mintAuthority: payer.publicKey, + recipient: payer.publicKey, + mintAccount: mintKeypair.publicKey, + associatedTokenAccount: associatedTokenAccountAddress, + }) + .rpc(); - console.log("Success!"); - console.log( - ` Associated Token Account Address: ${associatedTokenAccountAddress}`, - ); - console.log(` Transaction Signature: ${transactionSignature}`); - }); + console.log("Success!"); + console.log(` Associated Token Account Address: ${associatedTokenAccountAddress}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); }); diff --git a/tokens/spl-token-minter/anchor/tests/fixtures/mpl_token_metadata.so b/tokens/spl-token-minter/anchor/tests/fixtures/mpl_token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/spl-token-minter/anchor/tests/fixtures/mpl_token_metadata.so differ diff --git a/tokens/spl-token-minter/anchor/tests/fixtures/token_metadata.so b/tokens/spl-token-minter/anchor/tests/fixtures/token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/spl-token-minter/anchor/tests/fixtures/token_metadata.so differ diff --git a/tokens/spl-token-minter/anchor/tests/test.ts b/tokens/spl-token-minter/anchor/tests/test.ts index d06dad462..d3d94516b 100644 --- a/tokens/spl-token-minter/anchor/tests/test.ts +++ b/tokens/spl-token-minter/anchor/tests/test.ts @@ -5,61 +5,55 @@ import { BN } from "bn.js"; import type { SplTokenMinter } from "../target/types/spl_token_minter"; describe("SPL Token Minter", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - const program = anchor.workspace - .SplTokenMinter as anchor.Program; - - const metadata = { - name: "Solana Gold", - symbol: "GOLDSOL", - uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", - }; - - // Generate new keypair to use as address for mint account. - const mintKeypair = new Keypair(); - - it("Create an SPL Token!", async () => { - const transactionSignature = await program.methods - .createToken(metadata.name, metadata.symbol, metadata.uri) - .accounts({ - payer: payer.publicKey, - mintAccount: mintKeypair.publicKey, - }) - .signers([mintKeypair]) - .rpc(); - - console.log("Success!"); - console.log(` Mint Address: ${mintKeypair.publicKey}`); - console.log(` Transaction Signature: ${transactionSignature}`); - }); - - it("Mint some tokens to your wallet!", async () => { - // Derive the associated token address account for the mint and payer. - const associatedTokenAccountAddress = getAssociatedTokenAddressSync( - mintKeypair.publicKey, - payer.publicKey, - ); - - // Amount of tokens to mint. - const amount = new BN(100); - - // Mint the tokens to the associated token account. - const transactionSignature = await program.methods - .mintToken(amount) - .accounts({ - mintAuthority: payer.publicKey, - recipient: payer.publicKey, - mintAccount: mintKeypair.publicKey, - associatedTokenAccount: associatedTokenAccountAddress, - }) - .rpc(); - - console.log("Success!"); - console.log( - ` Associated Token Account Address: ${associatedTokenAccountAddress}`, - ); - console.log(` Transaction Signature: ${transactionSignature}`); - }); + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const payer = provider.wallet as anchor.Wallet; + const program = anchor.workspace.SplTokenMinter as anchor.Program; + + const metadata = { + name: "Solana Gold", + symbol: "GOLDSOL", + uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", + }; + + // Generate new keypair to use as address for mint account. + const mintKeypair = new Keypair(); + + it("Create an SPL Token!", async () => { + const transactionSignature = await program.methods + .createToken(metadata.name, metadata.symbol, metadata.uri) + .accounts({ + payer: payer.publicKey, + mintAccount: mintKeypair.publicKey, + }) + .signers([mintKeypair]) + .rpc(); + + console.log("Success!"); + console.log(` Mint Address: ${mintKeypair.publicKey}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); + + it("Mint some tokens to your wallet!", async () => { + // Derive the associated token address account for the mint and payer. + const associatedTokenAccountAddress = getAssociatedTokenAddressSync(mintKeypair.publicKey, payer.publicKey); + + // Amount of tokens to mint. + const amount = new BN(100); + + // Mint the tokens to the associated token account. + const transactionSignature = await program.methods + .mintToken(amount) + .accounts({ + mintAuthority: payer.publicKey, + recipient: payer.publicKey, + mintAccount: mintKeypair.publicKey, + associatedTokenAccount: associatedTokenAccountAddress, + }) + .rpc(); + + console.log("Success!"); + console.log(` Associated Token Account Address: ${associatedTokenAccountAddress}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); }); diff --git a/tokens/spl-token-minter/native/tests/instructions.ts b/tokens/spl-token-minter/native/tests/instructions.ts index e62cde477..70df73542 100644 --- a/tokens/spl-token-minter/native/tests/instructions.ts +++ b/tokens/spl-token-minter/native/tests/instructions.ts @@ -1,4 +1,4 @@ -import * as borsh from 'borsh'; +import * as borsh from "borsh"; export enum SplMinterInstruction { Create = 0, @@ -7,17 +7,17 @@ export enum SplMinterInstruction { export const CreateTokenArgsSchema = { struct: { - instruction: 'u8', - token_title: 'string', - token_symbol: 'string', - token_uri: 'string', + instruction: "u8", + token_title: "string", + token_symbol: "string", + token_uri: "string", }, }; export const MintToArgsSchema = { struct: { - instruction: 'u8', - quantity: 'u64', + instruction: "u8", + quantity: "u64", }, }; diff --git a/tokens/spl-token-minter/native/tests/test.ts b/tokens/spl-token-minter/native/tests/test.ts index 9a9c956ab..e15166765 100644 --- a/tokens/spl-token-minter/native/tests/test.ts +++ b/tokens/spl-token-minter/native/tests/test.ts @@ -1,6 +1,6 @@ -import { Buffer } from 'node:buffer'; -import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from '@metaplex-foundation/mpl-token-metadata'; -import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from '@solana/spl-token'; +import { Buffer } from "node:buffer"; +import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata"; +import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from "@solana/spl-token"; import { Connection, Keypair, @@ -10,33 +10,34 @@ import { sendAndConfirmTransaction, Transaction, TransactionInstruction, -} from '@solana/web3.js'; -import { BN } from 'bn.js'; -import { borshSerialize, CreateTokenArgsSchema, MintToArgsSchema, SplMinterInstruction } from './instructions'; +} from "@solana/web3.js"; +import { BN } from "bn.js"; +import { borshSerialize, CreateTokenArgsSchema, MintToArgsSchema, SplMinterInstruction } from "./instructions"; function createKeypairFromFile(path: string): Keypair { - return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require('node:fs').readFileSync(path, 'utf-8')))); + return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require("node:fs").readFileSync(path, "utf-8")))); } -describe('SPL Token Minter', async () => { +describe("SPL Token Minter", async () => { // const connection = new Connection(`http://localhost:8899`, 'confirmed'); - const connection = new Connection('https://api.devnet.solana.com/', 'confirmed'); - const payer = createKeypairFromFile(`${require('node:os').homedir()}/.config/solana/id.json`); - const program = createKeypairFromFile('./program/target/deploy/program-keypair.json'); + const connection = new Connection("https://api.devnet.solana.com/", "confirmed"); + const payer = createKeypairFromFile(`${require("node:os").homedir()}/.config/solana/id.json`); + const program = createKeypairFromFile("./program/target/deploy/program-keypair.json"); const mintKeypair: Keypair = Keypair.generate(); - it('Create an SPL Token!', async () => { + it("Create an SPL Token!", async () => { const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; const instructionData = borshSerialize(CreateTokenArgsSchema, { instruction: SplMinterInstruction.Create, - token_title: 'Solana Gold', - token_symbol: 'GOLDSOL', - token_uri: 'https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json', + token_title: "Solana Gold", + token_symbol: "GOLDSOL", + token_uri: + "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", }); const ix = new TransactionInstruction({ @@ -60,12 +61,12 @@ describe('SPL Token Minter', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, mintKeypair]); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${mintKeypair.publicKey}`); console.log(` Tx Signature: ${sx}`); }); - it('Mint some tokens to your wallet!', async () => { + it("Mint some tokens to your wallet!", async () => { const associatedTokenAccountAddress = await getAssociatedTokenAddress(mintKeypair.publicKey, payer.publicKey); const instructionData = borshSerialize(MintToArgsSchema, { @@ -97,7 +98,7 @@ describe('SPL Token Minter', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]); - console.log('Success!'); + console.log("Success!"); console.log(` ATA Address: ${associatedTokenAccountAddress}`); console.log(` Tx Signature: ${sx}`); }); diff --git a/tokens/token-2022/basics/anchor/Anchor.toml b/tokens/token-2022/basics/anchor/Anchor.toml index be2283b26..91f84f721 100644 --- a/tokens/token-2022/basics/anchor/Anchor.toml +++ b/tokens/token-2022/basics/anchor/Anchor.toml @@ -2,22 +2,22 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false -[programs.localnet] -anchor = "6qNqxkRF791FXFeQwqYQLEzAbGiqDULC5SSHVsfRoG89" -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +anchor = "Gd65x65gsd55JTEbpbB7B5ukg8Q6hctXzyGcWiTmzxjK" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" -# This project has both bankrun and validator tests. No [test.validator] -# section needed because Token-2022 is built into the local validator -# and doesn't require cloning from mainnet. +[scripts] +test = "cargo test" + +[hooks] + [test] startup_wait = 25000 - -[scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +shutdown_wait = 2000 +upgradeable = false diff --git a/tokens/token-2022/basics/anchor/migrations/deploy.ts b/tokens/token-2022/basics/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/basics/anchor/migrations/deploy.ts +++ b/tokens/token-2022/basics/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/basics/anchor/package.json b/tokens/token-2022/basics/anchor/package.json index 5b2bb974f..790a0a4f1 100644 --- a/tokens/token-2022/basics/anchor/package.json +++ b/tokens/token-2022/basics/anchor/package.json @@ -1,23 +1,23 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/web3.js": "^1.98.4" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/web3.js": "^1.98.4" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/basics/anchor/pnpm-lock.yaml b/tokens/token-2022/basics/anchor/pnpm-lock.yaml index 5eaa9f1db..8c4b29df1 100644 --- a/tokens/token-2022/basics/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/basics/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': specifier: ^1.98.4 version: 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -48,18 +48,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -767,16 +767,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -794,7 +794,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/token-2022/basics/anchor/programs/basics/Cargo.toml b/tokens/token-2022/basics/anchor/programs/basics/Cargo.toml index 69e048e68..d0bbc6f05 100644 --- a/tokens/token-2022/basics/anchor/programs/basics/Cargo.toml +++ b/tokens/token-2022/basics/anchor/programs/basics/Cargo.toml @@ -20,8 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = { version = "1.0.0-rc.5", features= ["init-if-needed"]} # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-spl = "1.0.0" +anchor-lang = { version = "1.0.0", features= ["init-if-needed"]} + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/basics/anchor/programs/basics/src/lib.rs b/tokens/token-2022/basics/anchor/programs/basics/src/lib.rs index cccd6a657..461bfaa4e 100644 --- a/tokens/token-2022/basics/anchor/programs/basics/src/lib.rs +++ b/tokens/token-2022/basics/anchor/programs/basics/src/lib.rs @@ -4,7 +4,7 @@ use anchor_spl::token_interface::{ self, Mint, MintTo, TokenAccount, TokenInterface, TransferChecked, }; -declare_id!("6qNqxkRF791FXFeQwqYQLEzAbGiqDULC5SSHVsfRoG89"); +declare_id!("Gd65x65gsd55JTEbpbB7B5ukg8Q6hctXzyGcWiTmzxjK"); #[program] pub mod anchor { diff --git a/tokens/token-2022/basics/anchor/programs/basics/tests/test_basics.rs b/tokens/token-2022/basics/anchor/programs/basics/tests/test_basics.rs new file mode 100644 index 000000000..ca0d8da65 --- /dev/null +++ b/tokens/token-2022/basics/anchor/programs/basics/tests/test_basics.rs @@ -0,0 +1,169 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + assert_token_account_balance, create_wallet, send_transaction_from_instructions, + token_extensions::{ + get_token_extensions_account_address, TOKEN_EXTENSIONS_PROGRAM_ID, + }, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn associated_token_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = anchor::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/anchor.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_create_token_and_mint_and_transfer() { + let (mut svm, program_id, payer) = setup(); + + let token_name = "TestToken".to_string(); + + // Derive the mint PDA + let (mint, _bump) = Pubkey::find_program_address( + &[ + b"token-2022-token", + payer.pubkey().as_ref(), + token_name.as_bytes(), + ], + &program_id, + ); + + // Step 1: Create Token via the program's own instruction + let create_token_ix = Instruction::new_with_bytes( + program_id, + &anchor::instruction::CreateToken { + _token_name: token_name.clone(), + } + .data(), + anchor::accounts::CreateToken { + signer: payer.pubkey(), + mint, + system_program: system_program::id(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + } + .to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![create_token_ix], &[&payer], &payer.pubkey()).unwrap(); + + // Verify mint account exists + let mint_account = svm.get_account(&mint).expect("Mint account should exist"); + assert!(!mint_account.data.is_empty(), "Mint should have data"); + + svm.expire_blockhash(); + + // Step 2: Create Associated Token Account for payer via the program's own instruction + let payer_ata = get_token_extensions_account_address(&payer.pubkey(), &mint); + + let create_ata_ix = Instruction::new_with_bytes( + program_id, + &anchor::instruction::CreateAssociatedTokenAccount {}.data(), + anchor::accounts::CreateAssociatedTokenAccount { + signer: payer.pubkey(), + mint, + token_account: payer_ata, + system_program: system_program::id(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + associated_token_program: associated_token_program_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![create_ata_ix], &[&payer], &payer.pubkey()).unwrap(); + + // Verify ATA exists + let ata_account = svm + .get_account(&payer_ata) + .expect("Payer ATA should exist"); + assert!(!ata_account.data.is_empty(), "ATA should have data"); + + svm.expire_blockhash(); + + // Step 3: Mint tokens to payer ATA via the program's own instruction + let mint_amount: u64 = 200_000_000; + + let mint_token_ix = Instruction::new_with_bytes( + program_id, + &anchor::instruction::MintToken { + amount: mint_amount, + } + .data(), + anchor::accounts::MintToken { + signer: payer.pubkey(), + mint, + receiver: payer_ata, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + } + .to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![mint_token_ix], &[&payer], &payer.pubkey()).unwrap(); + + assert_token_account_balance( + &svm, + &payer_ata, + mint_amount, + &format!("Should have minted {} tokens", mint_amount), + ); + + svm.expire_blockhash(); + + // Step 4: Transfer tokens to receiver via the program's own instruction + let receiver = create_wallet(&mut svm, 1_000_000_000).unwrap(); + let receiver_ata = get_token_extensions_account_address(&receiver.pubkey(), &mint); + + let transfer_amount: u64 = 100; + + let transfer_ix = Instruction::new_with_bytes( + program_id, + &anchor::instruction::TransferToken { + amount: transfer_amount, + } + .data(), + anchor::accounts::TransferToken { + signer: payer.pubkey(), + from: payer_ata, + to: receiver.pubkey(), + to_ata: receiver_ata, + mint, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + associated_token_program: associated_token_program_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![transfer_ix], &[&payer], &payer.pubkey()).unwrap(); + + assert_token_account_balance( + &svm, + &receiver_ata, + transfer_amount, + &format!("Receiver should have {} tokens", transfer_amount), + ); + assert_token_account_balance( + &svm, + &payer_ata, + mint_amount - transfer_amount, + "Payer should have remaining tokens", + ); +} diff --git a/tokens/token-2022/basics/anchor/tests/anchor.ts b/tokens/token-2022/basics/anchor/tests/anchor.ts index f46a2078f..92e50943a 100644 --- a/tokens/token-2022/basics/anchor/tests/anchor.ts +++ b/tokens/token-2022/basics/anchor/tests/anchor.ts @@ -5,96 +5,72 @@ import BN from "bn.js"; import type { Anchor } from "../target/types/anchor"; describe("anchor", () => { - // Configure the client to use the local cluster. - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - - const program = anchor.workspace.Anchor as Program; - const connection = program.provider.connection; - const TOKEN_2022_PROGRAM_ID = new anchor.web3.PublicKey( - "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", - ); - const wallet = provider.wallet as anchor.Wallet; - const ATA_PROGRAM_ID = new anchor.web3.PublicKey( - "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", - ); - - const tokenName = "TestToken"; - const [mint] = anchor.web3.PublicKey.findProgramAddressSync( - [ - Buffer.from("token-2022-token"), - wallet.publicKey.toBytes(), - Buffer.from(tokenName), - ], - program.programId, - ); - const [payerATA] = anchor.web3.PublicKey.findProgramAddressSync( - [ - wallet.publicKey.toBytes(), - TOKEN_2022_PROGRAM_ID.toBytes(), - mint.toBytes(), - ], - ATA_PROGRAM_ID, - ); - - const receiver = anchor.web3.Keypair.generate(); - - const [receiverATA] = anchor.web3.PublicKey.findProgramAddressSync( - [ - receiver.publicKey.toBytes(), - TOKEN_2022_PROGRAM_ID.toBytes(), - mint.toBytes(), - ], - ATA_PROGRAM_ID, - ); - - it("Create Token-2022 Token", async () => { - await connection.requestAirdrop(receiver.publicKey, 1000000000); - await connection.requestAirdrop(wallet.publicKey, 1000000000); - const tx = new anchor.web3.Transaction(); - - const ix = await program.methods - .createToken(tokenName) - .accounts({ - signer: wallet.publicKey, - tokenProgram: TOKEN_2022_PROGRAM_ID, - }) - .instruction(); - - tx.add(ix); - - const sig = await sendAndConfirmTransaction( - program.provider.connection, - tx, - [wallet.payer], - ); - console.log("Your transaction signature", sig); - }); - - it("Initialize payer ATA", async () => { - const tx = new anchor.web3.Transaction(); - - const ix = await program.methods - .createAssociatedTokenAccount() - .accounts({ - tokenAccount: payerATA, - mint: mint, - signer: wallet.publicKey, - tokenProgram: TOKEN_2022_PROGRAM_ID, - }) - .instruction(); - - tx.add(ix); - - const sig = await sendAndConfirmTransaction( - program.provider.connection, - tx, - [wallet.payer], - ); - console.log("Your transaction signature", sig); - }); - - /* + // Configure the client to use the local cluster. + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + + const program = anchor.workspace.Anchor as Program; + const connection = program.provider.connection; + const TOKEN_2022_PROGRAM_ID = new anchor.web3.PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); + const wallet = provider.wallet as anchor.Wallet; + const ATA_PROGRAM_ID = new anchor.web3.PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"); + + const tokenName = "TestToken"; + const [mint] = anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("token-2022-token"), wallet.publicKey.toBytes(), Buffer.from(tokenName)], + program.programId, + ); + const [payerATA] = anchor.web3.PublicKey.findProgramAddressSync( + [wallet.publicKey.toBytes(), TOKEN_2022_PROGRAM_ID.toBytes(), mint.toBytes()], + ATA_PROGRAM_ID, + ); + + const receiver = anchor.web3.Keypair.generate(); + + const [receiverATA] = anchor.web3.PublicKey.findProgramAddressSync( + [receiver.publicKey.toBytes(), TOKEN_2022_PROGRAM_ID.toBytes(), mint.toBytes()], + ATA_PROGRAM_ID, + ); + + it("Create Token-2022 Token", async () => { + await connection.requestAirdrop(receiver.publicKey, 1000000000); + await connection.requestAirdrop(wallet.publicKey, 1000000000); + const tx = new anchor.web3.Transaction(); + + const ix = await program.methods + .createToken(tokenName) + .accounts({ + signer: wallet.publicKey, + tokenProgram: TOKEN_2022_PROGRAM_ID, + }) + .instruction(); + + tx.add(ix); + + const sig = await sendAndConfirmTransaction(program.provider.connection, tx, [wallet.payer]); + console.log("Your transaction signature", sig); + }); + + it("Initialize payer ATA", async () => { + const tx = new anchor.web3.Transaction(); + + const ix = await program.methods + .createAssociatedTokenAccount() + .accounts({ + tokenAccount: payerATA, + mint: mint, + signer: wallet.publicKey, + tokenProgram: TOKEN_2022_PROGRAM_ID, + }) + .instruction(); + + tx.add(ix); + + const sig = await sendAndConfirmTransaction(program.provider.connection, tx, [wallet.payer]); + console.log("Your transaction signature", sig); + }); + + /* // This instruction is included only as a reference, but is not required to run this test, because we are using "init" in the program's transfer instruction. The create_associated_token_account instruction on the program is provided as a reference as well. it("Initialize receiver ATA", async () => { const tx = new anchor.web3.Transaction(); @@ -119,52 +95,44 @@ describe("anchor", () => { }); */ - it("Mint Token to payer", async () => { - const tx = new anchor.web3.Transaction(); - - const ix = await program.methods - .mintToken(new BN(200000000)) - .accounts({ - mint: mint, - signer: wallet.publicKey, - receiver: payerATA, - tokenProgram: TOKEN_2022_PROGRAM_ID, - }) - .instruction(); - - tx.add(ix); - - const sig = await sendAndConfirmTransaction( - program.provider.connection, - tx, - [wallet.payer], - ); - console.log("Your transaction signature", sig); - }); - - // Using init in the transfer instruction, as init if needed is bot working with Token 2022 yet. - it("Transfer Token", async () => { - const tx = new anchor.web3.Transaction(); - - const ix = await program.methods - .transferToken(new BN(100)) - .accounts({ - mint: mint, - signer: wallet.publicKey, - from: payerATA, - to: receiver.publicKey, - tokenProgram: TOKEN_2022_PROGRAM_ID, - toAta: receiverATA, - }) - .instruction(); - - tx.add(ix); - - const sig = await sendAndConfirmTransaction( - program.provider.connection, - tx, - [wallet.payer], - ); - console.log("Your transaction signature", sig); - }); + it("Mint Token to payer", async () => { + const tx = new anchor.web3.Transaction(); + + const ix = await program.methods + .mintToken(new BN(200000000)) + .accounts({ + mint: mint, + signer: wallet.publicKey, + receiver: payerATA, + tokenProgram: TOKEN_2022_PROGRAM_ID, + }) + .instruction(); + + tx.add(ix); + + const sig = await sendAndConfirmTransaction(program.provider.connection, tx, [wallet.payer]); + console.log("Your transaction signature", sig); + }); + + // Using init in the transfer instruction, as init if needed is bot working with Token 2022 yet. + it("Transfer Token", async () => { + const tx = new anchor.web3.Transaction(); + + const ix = await program.methods + .transferToken(new BN(100)) + .accounts({ + mint: mint, + signer: wallet.publicKey, + from: payerATA, + to: receiver.publicKey, + tokenProgram: TOKEN_2022_PROGRAM_ID, + toAta: receiverATA, + }) + .instruction(); + + tx.add(ix); + + const sig = await sendAndConfirmTransaction(program.provider.connection, tx, [wallet.payer]); + console.log("Your transaction signature", sig); + }); }); diff --git a/tokens/token-2022/basics/anchor/tests/bankrun.test.ts b/tokens/token-2022/basics/anchor/tests/bankrun.test.ts index b62269651..2edae2ed8 100644 --- a/tokens/token-2022/basics/anchor/tests/bankrun.test.ts +++ b/tokens/token-2022/basics/anchor/tests/bankrun.test.ts @@ -11,95 +11,75 @@ const IDL = require("../target/idl/anchor.json"); const PROGRAM_ID = new PublicKey(IDL.address); describe("anchor", async () => { - const context = await startAnchor( - "", - [{ name: "anchor", programId: PROGRAM_ID }], - [], - ); - const provider = new BankrunProvider(context); - anchor.setProvider(provider); - const program = new anchor.Program(IDL, provider); - const client = context.banksClient; - const TOKEN_2022_PROGRAM_ID = new anchor.web3.PublicKey( - "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", - ); - const wallet = provider.wallet as anchor.Wallet; - const ATA_PROGRAM_ID = new anchor.web3.PublicKey( - "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", - ); - - const tokenName = "TestToken"; - const [mint] = anchor.web3.PublicKey.findProgramAddressSync( - [ - Buffer.from("token-2022-token"), - wallet.publicKey.toBytes(), - Buffer.from(tokenName), - ], - program.programId, - ); - const [payerATA] = anchor.web3.PublicKey.findProgramAddressSync( - [ - wallet.publicKey.toBytes(), - TOKEN_2022_PROGRAM_ID.toBytes(), - mint.toBytes(), - ], - ATA_PROGRAM_ID, - ); - - const receiver = anchor.web3.Keypair.generate(); - - const [receiverATA] = anchor.web3.PublicKey.findProgramAddressSync( - [ - receiver.publicKey.toBytes(), - TOKEN_2022_PROGRAM_ID.toBytes(), - mint.toBytes(), - ], - ATA_PROGRAM_ID, - ); - - it("Create Token-2022 Token", async () => { - // await connection.requestAirdrop(receiver.publicKey, 1000000000); - // await connection.requestAirdrop(wallet.publicKey, 1000000000); - const tx = new anchor.web3.Transaction(); - const [blockhash, _height] = await client.getLatestBlockhash(); - - const ix = await program.methods - .createToken(tokenName) - .accounts({ - signer: wallet.publicKey, - tokenProgram: TOKEN_2022_PROGRAM_ID, - }) - .instruction(); - - tx.recentBlockhash = blockhash; - tx.add(ix); - tx.sign(wallet.payer); - const sig = await client.processTransaction(tx); - console.log("Your transaction signature", sig); - }); - - it("Initialize payer ATA", async () => { - const tx = new anchor.web3.Transaction(); - const [blockhash, _height] = await client.getLatestBlockhash(); - - const ix = await program.methods - .createAssociatedTokenAccount() - .accounts({ - tokenAccount: payerATA, - mint: mint, - signer: wallet.publicKey, - tokenProgram: TOKEN_2022_PROGRAM_ID, - }) - .instruction(); - - tx.recentBlockhash = blockhash; - tx.add(ix); - tx.sign(wallet.payer); - const sig = await client.processTransaction(tx); - console.log("Your transaction signature", sig); - }); - - /* + const context = await startAnchor("", [{ name: "anchor", programId: PROGRAM_ID }], []); + const provider = new BankrunProvider(context); + anchor.setProvider(provider); + const program = new anchor.Program(IDL, provider); + const client = context.banksClient; + const TOKEN_2022_PROGRAM_ID = new anchor.web3.PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); + const wallet = provider.wallet as anchor.Wallet; + const ATA_PROGRAM_ID = new anchor.web3.PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"); + + const tokenName = "TestToken"; + const [mint] = anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("token-2022-token"), wallet.publicKey.toBytes(), Buffer.from(tokenName)], + program.programId, + ); + const [payerATA] = anchor.web3.PublicKey.findProgramAddressSync( + [wallet.publicKey.toBytes(), TOKEN_2022_PROGRAM_ID.toBytes(), mint.toBytes()], + ATA_PROGRAM_ID, + ); + + const receiver = anchor.web3.Keypair.generate(); + + const [receiverATA] = anchor.web3.PublicKey.findProgramAddressSync( + [receiver.publicKey.toBytes(), TOKEN_2022_PROGRAM_ID.toBytes(), mint.toBytes()], + ATA_PROGRAM_ID, + ); + + it("Create Token-2022 Token", async () => { + // await connection.requestAirdrop(receiver.publicKey, 1000000000); + // await connection.requestAirdrop(wallet.publicKey, 1000000000); + const tx = new anchor.web3.Transaction(); + const [blockhash, _height] = await client.getLatestBlockhash(); + + const ix = await program.methods + .createToken(tokenName) + .accounts({ + signer: wallet.publicKey, + tokenProgram: TOKEN_2022_PROGRAM_ID, + }) + .instruction(); + + tx.recentBlockhash = blockhash; + tx.add(ix); + tx.sign(wallet.payer); + const sig = await client.processTransaction(tx); + console.log("Your transaction signature", sig); + }); + + it("Initialize payer ATA", async () => { + const tx = new anchor.web3.Transaction(); + const [blockhash, _height] = await client.getLatestBlockhash(); + + const ix = await program.methods + .createAssociatedTokenAccount() + .accounts({ + tokenAccount: payerATA, + mint: mint, + signer: wallet.publicKey, + tokenProgram: TOKEN_2022_PROGRAM_ID, + }) + .instruction(); + + tx.recentBlockhash = blockhash; + tx.add(ix); + tx.sign(wallet.payer); + const sig = await client.processTransaction(tx); + console.log("Your transaction signature", sig); + }); + + /* // This instruction is included only as a reference, but is not required to run this test, because we are using "init" in the program's transfer instruction. The create_associated_token_account instruction on the program is provided as a reference as well. it("Initialize receiver ATA", async () => { const tx = new anchor.web3.Transaction(); @@ -124,48 +104,48 @@ describe("anchor", async () => { }); */ - it("Mint Token to payer", async () => { - const tx = new anchor.web3.Transaction(); - const [blockhash, _height] = await client.getLatestBlockhash(); - - const ix = await program.methods - .mintToken(new BN(200000000)) - .accounts({ - mint: mint, - signer: wallet.publicKey, - receiver: payerATA, - tokenProgram: TOKEN_2022_PROGRAM_ID, - }) - .instruction(); - - tx.recentBlockhash = blockhash; - tx.add(ix); - tx.sign(wallet.payer); - const sig = await client.processTransaction(tx); - console.log("Your transaction signature", sig); - }); - - // Using init in the transfer instruction, as init if needed is bot working with Token 2022 yet. - it("Transfer Token", async () => { - const tx = new anchor.web3.Transaction(); - const [blockhash, _height] = await client.getLatestBlockhash(); - - const ix = await program.methods - .transferToken(new BN(100)) - .accounts({ - mint: mint, - signer: wallet.publicKey, - from: payerATA, - to: receiver.publicKey, - tokenProgram: TOKEN_2022_PROGRAM_ID, - toAta: receiverATA, - }) - .instruction(); - - tx.recentBlockhash = blockhash; - tx.add(ix); - tx.sign(wallet.payer); - const sig = await client.processTransaction(tx); - console.log("Your transaction signature", sig); - }); + it("Mint Token to payer", async () => { + const tx = new anchor.web3.Transaction(); + const [blockhash, _height] = await client.getLatestBlockhash(); + + const ix = await program.methods + .mintToken(new BN(200000000)) + .accounts({ + mint: mint, + signer: wallet.publicKey, + receiver: payerATA, + tokenProgram: TOKEN_2022_PROGRAM_ID, + }) + .instruction(); + + tx.recentBlockhash = blockhash; + tx.add(ix); + tx.sign(wallet.payer); + const sig = await client.processTransaction(tx); + console.log("Your transaction signature", sig); + }); + + // Using init in the transfer instruction, as init if needed is bot working with Token 2022 yet. + it("Transfer Token", async () => { + const tx = new anchor.web3.Transaction(); + const [blockhash, _height] = await client.getLatestBlockhash(); + + const ix = await program.methods + .transferToken(new BN(100)) + .accounts({ + mint: mint, + signer: wallet.publicKey, + from: payerATA, + to: receiver.publicKey, + tokenProgram: TOKEN_2022_PROGRAM_ID, + toAta: receiverATA, + }) + .instruction(); + + tx.recentBlockhash = blockhash; + tx.add(ix); + tx.sign(wallet.payer); + const sig = await client.processTransaction(tx); + console.log("Your transaction signature", sig); + }); }); diff --git a/tokens/token-2022/cpi-guard/anchor/Anchor.toml b/tokens/token-2022/cpi-guard/anchor/Anchor.toml index 2de4c34ae..84ecbf174 100644 --- a/tokens/token-2022/cpi-guard/anchor/Anchor.toml +++ b/tokens/token-2022/cpi-guard/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -cpi_guard = "6tU3MEowU6oxxeDZLSxEwzcEZsZrhBJsfUR6xECvShid" - -# [registry] section removed — no longer used in Anchor 1.0 +cpi_guard = "PWPfSkM5ntHyS68woBexCrrDVE23AdtdQbUoyx5q7GR" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/cpi-guard/anchor/migrations/deploy.ts b/tokens/token-2022/cpi-guard/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/cpi-guard/anchor/migrations/deploy.ts +++ b/tokens/token-2022/cpi-guard/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/cpi-guard/anchor/package.json b/tokens/token-2022/cpi-guard/anchor/package.json index ec93e2a0e..78c8eba57 100644 --- a/tokens/token-2022/cpi-guard/anchor/package.json +++ b/tokens/token-2022/cpi-guard/anchor/package.json @@ -1,23 +1,23 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/cpi-guard/anchor/pnpm-lock.yaml b/tokens/token-2022/cpi-guard/anchor/pnpm-lock.yaml index e2f036e39..4d2f0bd66 100644 --- a/tokens/token-2022/cpi-guard/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/cpi-guard/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.6 version: 0.4.14(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -48,18 +48,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -846,16 +846,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -873,7 +873,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/Cargo.toml b/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/Cargo.toml index 1d2b8f3dc..f2ced8eca 100644 --- a/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/Cargo.toml +++ b/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/Cargo.toml @@ -20,8 +20,16 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/src/lib.rs b/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/src/lib.rs index 25419c3f7..adbf6cc97 100644 --- a/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/src/lib.rs +++ b/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/src/lib.rs @@ -6,7 +6,7 @@ use anchor_spl::{ // Note that you cannot initialize or update the CpiGuard extension through a CPI // https://github.com/solana-labs/solana-program-library/blob/6968859e2ee0a1764da572de340cdb58e2b4586f/token/program-2022/src/extension/cpi_guard/processor.rs#L44-L46 -declare_id!("6tU3MEowU6oxxeDZLSxEwzcEZsZrhBJsfUR6xECvShid"); +declare_id!("PWPfSkM5ntHyS68woBexCrrDVE23AdtdQbUoyx5q7GR"); #[program] pub mod cpi_guard { diff --git a/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/tests/test_cpi_guard.rs b/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/tests/test_cpi_guard.rs new file mode 100644 index 000000000..378b35503 --- /dev/null +++ b/tokens/token-2022/cpi-guard/anchor/programs/cpi-guard/tests/test_cpi_guard.rs @@ -0,0 +1,205 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + assert_token_account_balance, create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_mint, mint_tokens_to_token_extensions_account, + TOKEN_EXTENSIONS_PROGRAM_ID, + }, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = cpi_guard::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/cpi_guard.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +/// Create a basic Token Extensions token account (165 bytes, no extensions). +/// Uses explicit keypair — kite's ATA creation won't work here because +/// we need to reallocate and add the CPI Guard extension later. +fn create_basic_token_account_instructions( + payer: &Pubkey, + token_account: &Pubkey, + mint: &Pubkey, + owner: &Pubkey, +) -> Vec { + let rent_sysvar: Pubkey = "SysvarRent111111111111111111111111111111111" + .parse() + .unwrap(); + let create_account_ix = anchor_lang::solana_program::system_instruction::create_account( + payer, + token_account, + 3_000_000, + 165, + &TOKEN_EXTENSIONS_PROGRAM_ID, + ); + let init_account_ix = Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*token_account, false), + AccountMeta::new_readonly(*mint, false), + AccountMeta::new_readonly(*owner, false), + AccountMeta::new_readonly(rent_sysvar, false), + ], + data: vec![1], // InitializeAccount + }; + vec![create_account_ix, init_account_ix] +} + +/// Reallocate instruction (instruction 29) to add extension types to a token account. +fn reallocate_instruction( + token_account: &Pubkey, + payer: &Pubkey, + owner: &Pubkey, + extension_types: &[u16], +) -> Instruction { + let mut data = vec![29u8]; + for et in extension_types { + data.extend_from_slice(&et.to_le_bytes()); + } + Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*token_account, false), + AccountMeta::new(*payer, true), + AccountMeta::new_readonly(system_program::id(), false), + AccountMeta::new_readonly(*owner, true), + ], + data, + } +} + +/// EnableCpiGuard instruction (instruction 34, sub-instruction 0). +fn enable_cpi_guard_instruction(token_account: &Pubkey, owner: &Pubkey) -> Instruction { + Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*token_account, false), + AccountMeta::new_readonly(*owner, true), + ], + data: vec![34, 0], + } +} + +/// DisableCpiGuard instruction (instruction 34, sub-instruction 1). +fn disable_cpi_guard_instruction(token_account: &Pubkey, owner: &Pubkey) -> Instruction { + Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*token_account, false), + AccountMeta::new_readonly(*owner, true), + ], + data: vec![34, 1], + } +} + +#[test] +fn test_cpi_guard_prevents_transfer_then_allows_after_disable() { + let (mut svm, program_id, payer) = setup(); + let token_keypair = Keypair::new(); + + // Step 1: Create a Token Extensions mint (no extensions needed on the mint itself) + let mint = create_token_extensions_mint(&mut svm, &payer, 2, None, &[]).unwrap(); + svm.expire_blockhash(); + + // Step 2: Create basic token account (needs explicit keypair for reallocate flow) + let token_ixs = create_basic_token_account_instructions( + &payer.pubkey(), + &token_keypair.pubkey(), + &mint, + &payer.pubkey(), + ); + send_transaction_from_instructions(&mut svm, token_ixs, &[&payer, &token_keypair], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 3: Reallocate to add CPI Guard extension space + let cpi_guard_extension_type: u16 = 11; // ExtensionType::CpiGuard + let reallocate_ix = reallocate_instruction( + &token_keypair.pubkey(), + &payer.pubkey(), + &payer.pubkey(), + &[cpi_guard_extension_type], + ); + send_transaction_from_instructions(&mut svm, vec![reallocate_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 4: Enable CPI Guard + let enable_ix = enable_cpi_guard_instruction(&token_keypair.pubkey(), &payer.pubkey()); + send_transaction_from_instructions(&mut svm, vec![enable_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 5: Mint 1 token to the token account + mint_tokens_to_token_extensions_account( + &mut svm, + &mint, + &token_keypair.pubkey(), + 1, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 6: Try CPI transfer — should fail because CPI Guard is enabled + let (recipient_token_account, _bump) = + Pubkey::find_program_address(&[b"pda"], &program_id); + + let transfer_ix = Instruction::new_with_bytes( + program_id, + &cpi_guard::instruction::CpiTransfer {}.data(), + cpi_guard::accounts::CpiTransfer { + sender: payer.pubkey(), + sender_token_account: token_keypair.pubkey(), + recipient_token_account, + mint_account: mint, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + let result = send_transaction_from_instructions(&mut svm, vec![transfer_ix], &[&payer], &payer.pubkey()); + assert!( + result.is_err(), + "Transfer should fail when CPI Guard is enabled" + ); + svm.expire_blockhash(); + + // Step 7: Disable CPI Guard + let disable_ix = disable_cpi_guard_instruction(&token_keypair.pubkey(), &payer.pubkey()); + send_transaction_from_instructions(&mut svm, vec![disable_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 8: Transfer should now succeed + let transfer_ix2 = Instruction::new_with_bytes( + program_id, + &cpi_guard::instruction::CpiTransfer {}.data(), + cpi_guard::accounts::CpiTransfer { + sender: payer.pubkey(), + sender_token_account: token_keypair.pubkey(), + recipient_token_account, + mint_account: mint, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![transfer_ix2], &[&payer], &payer.pubkey()).unwrap(); + + assert_token_account_balance(&svm, &recipient_token_account, 1, "Recipient should have 1 token"); +} diff --git a/tokens/token-2022/cpi-guard/anchor/tests/cpi-guard.ts b/tokens/token-2022/cpi-guard/anchor/tests/cpi-guard.ts index 6a727a599..f9b3969b4 100644 --- a/tokens/token-2022/cpi-guard/anchor/tests/cpi-guard.ts +++ b/tokens/token-2022/cpi-guard/anchor/tests/cpi-guard.ts @@ -1,5 +1,5 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; import { createEnableCpiGuardInstruction, createInitializeAccountInstruction, @@ -9,11 +9,11 @@ import { getAccountLen, mintTo, TOKEN_2022_PROGRAM_ID, -} from '@solana/spl-token'; -import { SystemProgram, sendAndConfirmTransaction, Transaction } from '@solana/web3.js'; -import type { CpiGuard } from '../target/types/cpi_guard'; +} from "@solana/spl-token"; +import { SystemProgram, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; +import type { CpiGuard } from "../target/types/cpi_guard"; -describe('cpi-guard', () => { +describe("cpi-guard", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); const connection = provider.connection; @@ -25,7 +25,7 @@ describe('cpi-guard', () => { const mintKeypair = new anchor.web3.Keypair(); const tokenKeypair = new anchor.web3.Keypair(); - it('Create Token Account with CpiGuard extension', async () => { + it("Create Token Account with CpiGuard extension", async () => { await createMint( connection, wallet.payer, // Payer of the transaction and initialization fees @@ -60,9 +60,18 @@ describe('cpi-guard', () => { ); // Instruction to initialize the CpiGuard Extension - const enableCpiGuiardInstruction = createEnableCpiGuardInstruction(tokenKeypair.publicKey, wallet.publicKey, [], TOKEN_2022_PROGRAM_ID); + const enableCpiGuiardInstruction = createEnableCpiGuardInstruction( + tokenKeypair.publicKey, + wallet.publicKey, + [], + TOKEN_2022_PROGRAM_ID, + ); - const transaction = new Transaction().add(createAccountInstruction, initializeAccountInstruction, enableCpiGuiardInstruction); + const transaction = new Transaction().add( + createAccountInstruction, + initializeAccountInstruction, + enableCpiGuiardInstruction, + ); const transactionSignature = await sendAndConfirmTransaction( connection, @@ -70,12 +79,22 @@ describe('cpi-guard', () => { [wallet.payer, tokenKeypair], // Signers ); - await mintTo(connection, wallet.payer, mintKeypair.publicKey, tokenKeypair.publicKey, wallet.payer, 1, [], null, TOKEN_2022_PROGRAM_ID); + await mintTo( + connection, + wallet.payer, + mintKeypair.publicKey, + tokenKeypair.publicKey, + wallet.payer, + 1, + [], + null, + TOKEN_2022_PROGRAM_ID, + ); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Transfer, expect fail', async () => { + it("Transfer, expect fail", async () => { try { await program.methods .cpiTransfer() @@ -86,16 +105,21 @@ describe('cpi-guard', () => { }) .rpc({ skipPreflight: true }); } catch (error) { - console.log('\nExpect Error:', error.message); + console.log("\nExpect Error:", error.message); } }); - it('Disable CpiGuard', async () => { - const transactionSignature = await disableCpiGuard(connection, wallet.payer, tokenKeypair.publicKey, wallet.publicKey); - console.log('Your transaction signature', transactionSignature); + it("Disable CpiGuard", async () => { + const transactionSignature = await disableCpiGuard( + connection, + wallet.payer, + tokenKeypair.publicKey, + wallet.publicKey, + ); + console.log("Your transaction signature", transactionSignature); }); - it('Transfer, expect success', async () => { + it("Transfer, expect success", async () => { const transactionSignature = await program.methods .cpiTransfer() .accounts({ @@ -104,6 +128,6 @@ describe('cpi-guard', () => { mintAccount: mintKeypair.publicKey, }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); }); diff --git a/tokens/token-2022/default-account-state/anchor/Anchor.toml b/tokens/token-2022/default-account-state/anchor/Anchor.toml index a6d6e4ee0..c3916c51e 100644 --- a/tokens/token-2022/default-account-state/anchor/Anchor.toml +++ b/tokens/token-2022/default-account-state/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -default_account_state = "5LdYbHiUsFxVG8bfqoeBkhBYMRmWZb3BoLuABgYW7coB" - -# [registry] section removed — no longer used in Anchor 1.0 +default_account_state = "HVMebUevbwW8QbUxSyCtNwsJcpgWj9jVkW38g69hTHRT" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/default-account-state/anchor/migrations/deploy.ts b/tokens/token-2022/default-account-state/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/default-account-state/anchor/migrations/deploy.ts +++ b/tokens/token-2022/default-account-state/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/default-account-state/anchor/package.json b/tokens/token-2022/default-account-state/anchor/package.json index f800607c4..cc320fb64 100644 --- a/tokens/token-2022/default-account-state/anchor/package.json +++ b/tokens/token-2022/default-account-state/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/default-account-state/anchor/pnpm-lock.yaml b/tokens/token-2022/default-account-state/anchor/pnpm-lock.yaml index 4ad69fa59..6470efa7e 100644 --- a/tokens/token-2022/default-account-state/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/default-account-state/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.6 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -860,16 +860,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -887,7 +887,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/default-account-state/anchor/programs/default-account-state/Cargo.toml b/tokens/token-2022/default-account-state/anchor/programs/default-account-state/Cargo.toml index d596d8b63..5537d63af 100644 --- a/tokens/token-2022/default-account-state/anchor/programs/default-account-state/Cargo.toml +++ b/tokens/token-2022/default-account-state/anchor/programs/default-account-state/Cargo.toml @@ -20,8 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/default-account-state/anchor/programs/default-account-state/src/lib.rs b/tokens/token-2022/default-account-state/anchor/programs/default-account-state/src/lib.rs index c1b5c3da6..c03c2cb1c 100644 --- a/tokens/token-2022/default-account-state/anchor/programs/default-account-state/src/lib.rs +++ b/tokens/token-2022/default-account-state/anchor/programs/default-account-state/src/lib.rs @@ -12,7 +12,7 @@ use anchor_spl::{ }, }; -declare_id!("5LdYbHiUsFxVG8bfqoeBkhBYMRmWZb3BoLuABgYW7coB"); +declare_id!("HVMebUevbwW8QbUxSyCtNwsJcpgWj9jVkW38g69hTHRT"); #[program] pub mod default_account_state { diff --git a/tokens/token-2022/default-account-state/anchor/programs/default-account-state/tests/test_default_account_state.rs b/tokens/token-2022/default-account-state/anchor/programs/default-account-state/tests/test_default_account_state.rs new file mode 100644 index 000000000..c0666812b --- /dev/null +++ b/tokens/token-2022/default-account-state/anchor/programs/default-account-state/tests/test_default_account_state.rs @@ -0,0 +1,165 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + assert_token_account_balance, create_wallet, send_transaction_from_instructions, + token_extensions::{ + mint_tokens_to_token_extensions_account, TOKEN_EXTENSIONS_PROGRAM_ID, + }, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +/// Create a Token Extensions token account (165 bytes, no extra extensions). +/// Uses explicit keypair — not an ATA — so we can inspect account state bytes. +fn create_token_account_instruction( + payer: &Pubkey, + token_account: &Pubkey, + mint: &Pubkey, + owner: &Pubkey, +) -> Vec { + let rent_sysvar: Pubkey = "SysvarRent111111111111111111111111111111111" + .parse() + .unwrap(); + let create_ix = anchor_lang::solana_program::system_instruction::create_account( + payer, + token_account, + 3_000_000, + 165, + &TOKEN_EXTENSIONS_PROGRAM_ID, + ); + let init_ix = Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*token_account, false), + AccountMeta::new_readonly(*mint, false), + AccountMeta::new_readonly(*owner, false), + AccountMeta::new_readonly(rent_sysvar, false), + ], + data: vec![1], // InitializeAccount + }; + vec![create_ix, init_ix] +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = default_account_state::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/default_account_state.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_default_account_state() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + + // Step 1: Initialize mint with DefaultAccountState extension (frozen) + let initialize_ix = Instruction::new_with_bytes( + program_id, + &default_account_state::instruction::Initialize {}.data(), + default_account_state::accounts::Initialize { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Verify mint exists + let mint_account = svm.get_account(&mint_keypair.pubkey()).unwrap(); + assert!(!mint_account.data.is_empty(), "Mint should have data"); + + // Step 2: Create a token account (it will be frozen by default due to DefaultAccountState extension) + let token1 = Keypair::new(); + let create_token1_ixs = create_token_account_instruction( + &payer.pubkey(), + &token1.pubkey(), + &mint_keypair.pubkey(), + &payer.pubkey(), + ); + send_transaction_from_instructions(&mut svm, create_token1_ixs, &[&payer, &token1], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Verify token account state is frozen (byte 108 = account state: 0=uninitialized, 1=initialized, 2=frozen) + let token1_data = svm.get_account(&token1.pubkey()).unwrap(); + assert_eq!( + token1_data.data[108], 2, + "Token account should be frozen (state=2)" + ); + + // Step 3: Attempt to mint to the frozen account — should fail + let result = mint_tokens_to_token_extensions_account( + &mut svm, + &mint_keypair.pubkey(), + &token1.pubkey(), + 1, + &payer, + ); + assert!( + result.is_err(), + "Minting to a frozen account should fail" + ); + svm.expire_blockhash(); + + // Step 4: Update default state to Initialized + let update_ix = Instruction::new_with_bytes( + program_id, + &default_account_state::instruction::UpdateDefaultState { + account_state: default_account_state::AnchorAccountState::Initialized, + } + .data(), + default_account_state::accounts::UpdateDefaultState { + freeze_authority: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![update_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 5: Create a new token account — should be initialized (not frozen) now + let token2 = Keypair::new(); + let create_token2_ixs = create_token_account_instruction( + &payer.pubkey(), + &token2.pubkey(), + &mint_keypair.pubkey(), + &payer.pubkey(), + ); + send_transaction_from_instructions(&mut svm, create_token2_ixs, &[&payer, &token2], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Verify token2 is initialized (not frozen) + let token2_data = svm.get_account(&token2.pubkey()).unwrap(); + assert_eq!( + token2_data.data[108], 1, + "Token account should be initialized (state=1)" + ); + + // Step 6: Mint to the new account — should succeed + mint_tokens_to_token_extensions_account( + &mut svm, + &mint_keypair.pubkey(), + &token2.pubkey(), + 1, + &payer, + ).unwrap(); + + assert_token_account_balance(&svm, &token2.pubkey(), 1, "Should have minted 1 token"); +} diff --git a/tokens/token-2022/default-account-state/anchor/tests/default-account-state.ts b/tokens/token-2022/default-account-state/anchor/tests/default-account-state.ts index ae32cccbb..3e82cc4c2 100644 --- a/tokens/token-2022/default-account-state/anchor/tests/default-account-state.ts +++ b/tokens/token-2022/default-account-state/anchor/tests/default-account-state.ts @@ -1,9 +1,9 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { createAccount, mintTo, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import type { DefaultAccountState } from '../target/types/default_account_state'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { createAccount, mintTo, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import type { DefaultAccountState } from "../target/types/default_account_state"; -describe('default-account-state', () => { +describe("default-account-state", () => { const provider = anchor.AnchorProvider.env(); const connection = provider.connection; const wallet = provider.wallet as anchor.Wallet; @@ -13,16 +13,16 @@ describe('default-account-state', () => { const mintKeypair = new anchor.web3.Keypair(); - it('Create Mint with DefaultAccountState extension', async () => { + it("Create Mint with DefaultAccountState extension", async () => { const transactionSignature = await program.methods .initialize() .accounts({ mintAccount: mintKeypair.publicKey }) .signers([mintKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Attempt Mint Token, expect fail', async () => { + it("Attempt Mint Token, expect fail", async () => { const amount = 1; // Create a token account, default state is frozen @@ -50,20 +50,20 @@ describe('default-account-state', () => { TOKEN_2022_PROGRAM_ID, // Token Extension Program ID ); } catch (error) { - console.log('\nExpect Error:', error.logs); + console.log("\nExpect Error:", error.logs); } }); - it('Update DefaultAccountState', async () => { + it("Update DefaultAccountState", async () => { // Update the default state to initialized (not frozen) const transactionSignature = await program.methods .updateDefaultState({ initialized: {} }) .accounts({ mintAccount: mintKeypair.publicKey }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Attempt Mint Token, expect success', async () => { + it("Attempt Mint Token, expect success", async () => { const amount = 1; // Create a token account, default state is initialized (not frozen) diff --git a/tokens/token-2022/default-account-state/native/tests/test.ts b/tokens/token-2022/default-account-state/native/tests/test.ts index 01631bd34..381e14945 100644 --- a/tokens/token-2022/default-account-state/native/tests/test.ts +++ b/tokens/token-2022/default-account-state/native/tests/test.ts @@ -1,24 +1,30 @@ -import { Buffer } from 'node:buffer'; -import { describe, test } from 'node:test'; -import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import { Keypair, PublicKey, SYSVAR_RENT_PUBKEY, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { assert } from 'chai'; -import { start } from 'solana-bankrun'; +import { Buffer } from "node:buffer"; +import { describe, test } from "node:test"; +import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import { + Keypair, + PublicKey, + SYSVAR_RENT_PUBKEY, + SystemProgram, + Transaction, + TransactionInstruction, +} from "@solana/web3.js"; +import * as borsh from "borsh"; +import { assert } from "chai"; +import { start } from "solana-bankrun"; - -const CreateTokenArgsSchema = { struct: { token_decimals: 'u8' } }; +const CreateTokenArgsSchema = { struct: { token_decimals: "u8" } }; function borshSerialize(schema: borsh.Schema, data: object): Buffer { return Buffer.from(borsh.serialize(schema, data)); } -describe('Create Token', async () => { +describe("Create Token", async () => { const PROGRAM_ID = PublicKey.unique(); const context = await start( [ { - name: 'token_2022_default_account_state_program', + name: "token_2022_default_account_state_program", programId: PROGRAM_ID, }, ], @@ -27,7 +33,7 @@ describe('Create Token', async () => { const client = context.banksClient; const payer = context.payer; - test('Create a Token-22 SPL-Token !', async () => { + test("Create a Token-22 SPL-Token !", async () => { const blockhash = context.lastBlockhash; const mintKeypair: Keypair = Keypair.generate(); @@ -56,6 +62,6 @@ describe('Create Token', async () => { const transaction = await client.processTransaction(tx); assert(transaction.logMessages[0].startsWith(`Program ${PROGRAM_ID}`)); - console.log('Token Mint Address: ', mintKeypair.publicKey.toBase58()); + console.log("Token Mint Address: ", mintKeypair.publicKey.toBase58()); }); }); diff --git a/tokens/token-2022/group/anchor/Anchor.toml b/tokens/token-2022/group/anchor/Anchor.toml index f3192c85d..b6a1e6c30 100644 --- a/tokens/token-2022/group/anchor/Anchor.toml +++ b/tokens/token-2022/group/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -group = "4XCDGMD8fsdjUzmYj6d9if8twFt1f23Ym52iDmWK8fFs" - -# [registry] section removed — no longer used in Anchor 1.0 +group = "8cToQMRhi1w6SLMLCcPniNix9eivQV3oFWwPucR5XxdR" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/group/anchor/migrations/deploy.ts b/tokens/token-2022/group/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/group/anchor/migrations/deploy.ts +++ b/tokens/token-2022/group/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/group/anchor/package.json b/tokens/token-2022/group/anchor/package.json index 198383d3f..4c69440ef 100644 --- a/tokens/token-2022/group/anchor/package.json +++ b/tokens/token-2022/group/anchor/package.json @@ -1,20 +1,20 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/group/anchor/pnpm-lock.yaml b/tokens/token-2022/group/anchor/pnpm-lock.yaml index 5e7783487..243a77181 100644 --- a/tokens/token-2022/group/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/group/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) devDependencies: '@types/bn.js': specifier: ^5.1.0 @@ -39,18 +39,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -705,16 +705,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -732,7 +732,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/token-2022/group/anchor/programs/group/Cargo.toml b/tokens/token-2022/group/anchor/programs/group/Cargo.toml index ceda62bcf..b8941f668 100644 --- a/tokens/token-2022/group/anchor/programs/group/Cargo.toml +++ b/tokens/token-2022/group/anchor/programs/group/Cargo.toml @@ -20,9 +20,16 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -spl-token-group-interface = "0.2.5" +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" +# spl-token-group-interface removed — unused, caused version conflicts with litesvm + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/group/anchor/programs/group/src/lib.rs b/tokens/token-2022/group/anchor/programs/group/src/lib.rs index f817c5c13..0cbe25339 100644 --- a/tokens/token-2022/group/anchor/programs/group/src/lib.rs +++ b/tokens/token-2022/group/anchor/programs/group/src/lib.rs @@ -8,7 +8,7 @@ use anchor_spl::token_interface::{ token_group_initialize, Mint, Token2022, TokenGroupInitialize, }; -declare_id!("4XCDGMD8fsdjUzmYj6d9if8twFt1f23Ym52iDmWK8fFs"); +declare_id!("8cToQMRhi1w6SLMLCcPniNix9eivQV3oFWwPucR5XxdR"); #[program] pub mod group { diff --git a/tokens/token-2022/group/anchor/programs/group/tests/test_group.rs b/tokens/token-2022/group/anchor/programs/group/tests/test_group.rs new file mode 100644 index 000000000..4d6135a04 --- /dev/null +++ b/tokens/token-2022/group/anchor/programs/group/tests/test_group.rs @@ -0,0 +1,50 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::TOKEN_EXTENSIONS_PROGRAM_ID, + }, + solana_signer::Signer, +}; + +#[test] +fn test_initialize_group() { + let program_id = group::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/group.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + // Derive the mint PDA + let (mint_account, _bump) = Pubkey::find_program_address(&[b"group"], &program_id); + + let instruction = Instruction::new_with_bytes( + program_id, + &group::instruction::TestInitializeGroup {}.data(), + group::accounts::InitializeGroup { + payer: payer.pubkey(), + mint_account, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions(&mut svm, vec![instruction], &[&payer], &payer.pubkey()).unwrap(); + + // Verify mint was created with group pointer extension + let mint_data = svm + .get_account(&mint_account) + .expect("Mint account should exist"); + assert!( + mint_data.data.len() > 82, + "Mint should have extension data (size > 82, got {})", + mint_data.data.len() + ); +} diff --git a/tokens/token-2022/group/anchor/tests/group.ts b/tokens/token-2022/group/anchor/tests/group.ts index 7756b0ca3..c3344bce5 100644 --- a/tokens/token-2022/group/anchor/tests/group.ts +++ b/tokens/token-2022/group/anchor/tests/group.ts @@ -1,8 +1,8 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import type { Group } from '../target/types/group'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import type { Group } from "../target/types/group"; -describe('group', () => { +describe("group", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); const _connection = provider.connection; @@ -11,8 +11,8 @@ describe('group', () => { const program = anchor.workspace.Group as Program; - it('Create Mint with Group Pointer', async () => { + it("Create Mint with Group Pointer", async () => { const transactionSignature = await program.methods.testInitializeGroup().accounts({}).rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); }); diff --git a/tokens/token-2022/immutable-owner/anchor/Anchor.toml b/tokens/token-2022/immutable-owner/anchor/Anchor.toml index 8716f3857..98bbf37d4 100644 --- a/tokens/token-2022/immutable-owner/anchor/Anchor.toml +++ b/tokens/token-2022/immutable-owner/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -immutable_owner = "6g5URpqqurW8RbKjuGeRCVZBKky3J4kYcLeotQ6vj6UT" - -# [registry] section removed — no longer used in Anchor 1.0 +immutable_owner = "FwsJpDYJ1UkYHq6rGYD7sXY1fStiBTfLpApazzj9khS7" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/immutable-owner/anchor/migrations/deploy.ts b/tokens/token-2022/immutable-owner/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/immutable-owner/anchor/migrations/deploy.ts +++ b/tokens/token-2022/immutable-owner/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/immutable-owner/anchor/package.json b/tokens/token-2022/immutable-owner/anchor/package.json index f800607c4..cc320fb64 100644 --- a/tokens/token-2022/immutable-owner/anchor/package.json +++ b/tokens/token-2022/immutable-owner/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/immutable-owner/anchor/pnpm-lock.yaml b/tokens/token-2022/immutable-owner/anchor/pnpm-lock.yaml index bb8d11208..54f388346 100644 --- a/tokens/token-2022/immutable-owner/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/immutable-owner/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.6 version: 0.4.14(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -783,16 +783,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -810,7 +810,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/Cargo.toml b/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/Cargo.toml index 233e36b2c..a66b664fc 100644 --- a/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/Cargo.toml +++ b/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/Cargo.toml @@ -20,8 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/src/lib.rs b/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/src/lib.rs index 47c6a53ee..2e53bb1c2 100644 --- a/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/src/lib.rs +++ b/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/src/lib.rs @@ -9,7 +9,7 @@ use anchor_spl::{ token_interface::{immutable_owner_initialize, ImmutableOwnerInitialize, Mint, Token2022}, }; -declare_id!("6g5URpqqurW8RbKjuGeRCVZBKky3J4kYcLeotQ6vj6UT"); +declare_id!("FwsJpDYJ1UkYHq6rGYD7sXY1fStiBTfLpApazzj9khS7"); #[program] pub mod immutable_owner { diff --git a/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/tests/test_immutable_owner.rs b/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/tests/test_immutable_owner.rs new file mode 100644 index 000000000..dad6478b0 --- /dev/null +++ b/tokens/token-2022/immutable-owner/anchor/programs/immutable-owner/tests/test_immutable_owner.rs @@ -0,0 +1,106 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::{create_token_extensions_mint, TOKEN_EXTENSIONS_PROGRAM_ID}, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +/// SetAuthority instruction for Token Extensions (instruction 6). +fn set_authority_instruction( + account: &Pubkey, + current_authority: &Pubkey, + new_authority: Option<&Pubkey>, + authority_type: u8, +) -> Instruction { + let mut data = vec![6u8, authority_type]; + match new_authority { + Some(new_auth) => { + data.push(1); // COption::Some + data.extend_from_slice(new_auth.as_ref()); + } + None => { + data.push(0); // COption::None + data.extend_from_slice(&[0u8; 32]); + } + } + Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*account, false), + AccountMeta::new_readonly(*current_authority, true), + ], + data, + } +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = immutable_owner::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/immutable_owner.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_create_token_account_with_immutable_owner() { + let (mut svm, program_id, payer) = setup(); + let token_keypair = Keypair::new(); + + // Step 1: Create a Token Extensions mint with 2 decimals (no extensions needed on mint) + let mint = create_token_extensions_mint(&mut svm, &payer, 2, None, &[]).unwrap(); + svm.expire_blockhash(); + + // Step 2: Call program to create token account with ImmutableOwner extension + let initialize_ix = Instruction::new_with_bytes( + program_id, + &immutable_owner::instruction::Initialize {}.data(), + immutable_owner::accounts::Initialize { + payer: payer.pubkey(), + token_account: token_keypair.pubkey(), + mint_account: mint, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &token_keypair], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Verify token account was created + let token_data = svm + .get_account(&token_keypair.pubkey()) + .expect("Token account should exist"); + assert!( + token_data.data.len() > 165, + "Token account should have extension data (size > 165, got {})", + token_data.data.len() + ); + + // Step 3: Attempt to change the account owner — should fail due to immutable owner + let new_owner = Keypair::new(); + let set_authority_ix = set_authority_instruction( + &token_keypair.pubkey(), + &payer.pubkey(), + Some(&new_owner.pubkey()), + 2, // AuthorityType::AccountOwner + ); + let result = send_transaction_from_instructions(&mut svm, vec![set_authority_ix], &[&payer], &payer.pubkey()); + assert!( + result.is_err(), + "Setting a new owner should fail due to ImmutableOwner extension" + ); +} diff --git a/tokens/token-2022/immutable-owner/anchor/tests/immutable-owner.ts b/tokens/token-2022/immutable-owner/anchor/tests/immutable-owner.ts index 8e2015dba..7202b1d5b 100644 --- a/tokens/token-2022/immutable-owner/anchor/tests/immutable-owner.ts +++ b/tokens/token-2022/immutable-owner/anchor/tests/immutable-owner.ts @@ -1,9 +1,9 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { AuthorityType, createMint, setAuthority, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import type { ImmutableOwner } from '../target/types/immutable_owner'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { AuthorityType, createMint, setAuthority, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import type { ImmutableOwner } from "../target/types/immutable_owner"; -describe('immutable-owner', () => { +describe("immutable-owner", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); const connection = provider.connection; @@ -14,7 +14,7 @@ describe('immutable-owner', () => { const tokenKeypair = new anchor.web3.Keypair(); - it('Create Token Account with ImmutableOwner extension', async () => { + it("Create Token Account with ImmutableOwner extension", async () => { const mint = await createMint( connection, wallet.payer, // Payer of the transaction and initialization fees @@ -34,10 +34,10 @@ describe('immutable-owner', () => { }) .signers([tokenKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Attempt to change token account owner, expect fail', async () => { + it("Attempt to change token account owner, expect fail", async () => { try { await setAuthority( connection, // Connection to use @@ -51,7 +51,7 @@ describe('immutable-owner', () => { TOKEN_2022_PROGRAM_ID, // Token Extension Program ID ); } catch (error) { - console.log('\nExpect Error:', error.logs); + console.log("\nExpect Error:", error.logs); } }); }); diff --git a/tokens/token-2022/interest-bearing/anchor/Anchor.toml b/tokens/token-2022/interest-bearing/anchor/Anchor.toml index f37dff156..6618e4fee 100644 --- a/tokens/token-2022/interest-bearing/anchor/Anchor.toml +++ b/tokens/token-2022/interest-bearing/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -interest_bearing = "DMQdkzRJz8uQSN8Kx2QYmQJn6xLKhsu3LcPYxs314MgC" - -# [registry] section removed — no longer used in Anchor 1.0 +interest_bearing = "2tinFpSK55kJu1wjcwW1PZBDF3HrP7PaYJjDCAFJMDD8" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/interest-bearing/anchor/migrations/deploy.ts b/tokens/token-2022/interest-bearing/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/interest-bearing/anchor/migrations/deploy.ts +++ b/tokens/token-2022/interest-bearing/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/interest-bearing/anchor/package.json b/tokens/token-2022/interest-bearing/anchor/package.json index f800607c4..cc320fb64 100644 --- a/tokens/token-2022/interest-bearing/anchor/package.json +++ b/tokens/token-2022/interest-bearing/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/interest-bearing/anchor/pnpm-lock.yaml b/tokens/token-2022/interest-bearing/anchor/pnpm-lock.yaml index 841b2d24e..349da1833 100644 --- a/tokens/token-2022/interest-bearing/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/interest-bearing/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.6 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -860,16 +860,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -887,7 +887,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/Cargo.toml b/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/Cargo.toml index 45359f68b..4de1d7d84 100644 --- a/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/Cargo.toml +++ b/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/Cargo.toml @@ -21,8 +21,15 @@ custom-panic = [] [dependencies] -anchor-lang = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/src/lib.rs b/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/src/lib.rs index bef10631e..104c325c2 100644 --- a/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/src/lib.rs +++ b/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/src/lib.rs @@ -19,7 +19,7 @@ use anchor_spl::{ InterestBearingMintUpdateRate, Mint, Token2022, }, }; -declare_id!("DMQdkzRJz8uQSN8Kx2QYmQJn6xLKhsu3LcPYxs314MgC"); +declare_id!("2tinFpSK55kJu1wjcwW1PZBDF3HrP7PaYJjDCAFJMDD8"); #[program] pub mod interest_bearing { diff --git a/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/tests/test_interest_bearing.rs b/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/tests/test_interest_bearing.rs new file mode 100644 index 000000000..c354d3ba7 --- /dev/null +++ b/tokens/token-2022/interest-bearing/anchor/programs/interest-bearing/tests/test_interest_bearing.rs @@ -0,0 +1,72 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::TOKEN_EXTENSIONS_PROGRAM_ID, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = interest_bearing::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/interest_bearing.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_initialize_and_update_rate() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + + // Step 1: Initialize mint with InterestBearingConfig extension (rate=0) + let initialize_ix = Instruction::new_with_bytes( + program_id, + &interest_bearing::instruction::Initialize { rate: 0 }.data(), + interest_bearing::accounts::Initialize { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); + + // Verify mint account exists + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should exist"); + assert!(!mint_account.data.is_empty(), "Mint should have data"); + + svm.expire_blockhash(); + + // Step 2: Update the interest rate to 100 + let update_rate_ix = Instruction::new_with_bytes( + program_id, + &interest_bearing::instruction::UpdateRate { rate: 100 }.data(), + interest_bearing::accounts::UpdateRate { + authority: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![update_rate_ix], &[&payer], &payer.pubkey()).unwrap(); + + // Verify mint still exists after rate update + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should still exist"); + assert!(!mint_account.data.is_empty(), "Mint should still have data"); +} diff --git a/tokens/token-2022/interest-bearing/anchor/tests/interest-bearing.ts b/tokens/token-2022/interest-bearing/anchor/tests/interest-bearing.ts index 45a2938a7..bc1f83a19 100644 --- a/tokens/token-2022/interest-bearing/anchor/tests/interest-bearing.ts +++ b/tokens/token-2022/interest-bearing/anchor/tests/interest-bearing.ts @@ -1,9 +1,9 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { amountToUiAmount, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import type { InterestBearing } from '../target/types/interest_bearing'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { amountToUiAmount, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import type { InterestBearing } from "../target/types/interest_bearing"; -describe('interest-bearing', () => { +describe("interest-bearing", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); const connection = provider.connection; @@ -14,7 +14,7 @@ describe('interest-bearing', () => { const mintKeypair = new anchor.web3.Keypair(); - it('Create Mint with InterestBearingConfig extension', async () => { + it("Create Mint with InterestBearingConfig extension", async () => { const rate = 0; const transactionSignature = await program.methods @@ -22,17 +22,20 @@ describe('interest-bearing', () => { .accounts({ mintAccount: mintKeypair.publicKey }) .signers([mintKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Update Mint with Interest Rate', async () => { + it("Update Mint with Interest Rate", async () => { const rate = 100; - const transactionSignature = await program.methods.updateRate(rate).accounts({ mintAccount: mintKeypair.publicKey }).rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + const transactionSignature = await program.methods + .updateRate(rate) + .accounts({ mintAccount: mintKeypair.publicKey }) + .rpc({ skipPreflight: true }); + console.log("Your transaction signature", transactionSignature); }); - it('Calculate accrued interest', async () => { + it("Calculate accrued interest", async () => { await sleep(1); const amount = 1000; @@ -46,7 +49,7 @@ describe('interest-bearing', () => { TOKEN_2022_PROGRAM_ID, // Token Extension Program ID ); - console.log('\nAmount with Accrued Interest:', uiAmount); + console.log("\nAmount with Accrued Interest:", uiAmount); }); }); diff --git a/tokens/token-2022/memo-transfer/anchor/Anchor.toml b/tokens/token-2022/memo-transfer/anchor/Anchor.toml index 5ac2fc3c0..8a6ff1188 100644 --- a/tokens/token-2022/memo-transfer/anchor/Anchor.toml +++ b/tokens/token-2022/memo-transfer/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -memo_transfer = "5BQyC7y2Pc283woThq11uZRqsgcRbBRLKz4yQ8BJadi2" - -# [registry] section removed — no longer used in Anchor 1.0 +memo_transfer = "C3zvHFYvrYgydPXv6vPZkcZvx24YE6pTUTZmtQJnAZQs" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/memo-transfer/anchor/migrations/deploy.ts b/tokens/token-2022/memo-transfer/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/memo-transfer/anchor/migrations/deploy.ts +++ b/tokens/token-2022/memo-transfer/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/memo-transfer/anchor/package.json b/tokens/token-2022/memo-transfer/anchor/package.json index a3f2b8fe6..2e989a504 100644 --- a/tokens/token-2022/memo-transfer/anchor/package.json +++ b/tokens/token-2022/memo-transfer/anchor/package.json @@ -1,22 +1,22 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-memo": "^0.2.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-memo": "^0.2.5", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/memo-transfer/anchor/pnpm-lock.yaml b/tokens/token-2022/memo-transfer/anchor/pnpm-lock.yaml index 93e2d0007..79f0e36b2 100644 --- a/tokens/token-2022/memo-transfer/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/memo-transfer/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-memo': specifier: ^0.2.5 version: 0.2.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) @@ -45,18 +45,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -869,16 +869,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -896,7 +896,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/Cargo.toml b/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/Cargo.toml index e181b17b7..2fce0e80e 100644 --- a/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/Cargo.toml +++ b/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/Cargo.toml @@ -20,8 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/src/lib.rs b/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/src/lib.rs index afaaabc5e..122bc6da0 100644 --- a/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/src/lib.rs +++ b/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/src/lib.rs @@ -12,7 +12,7 @@ use anchor_spl::{ }, }; -declare_id!("5BQyC7y2Pc283woThq11uZRqsgcRbBRLKz4yQ8BJadi2"); +declare_id!("C3zvHFYvrYgydPXv6vPZkcZvx24YE6pTUTZmtQJnAZQs"); #[program] pub mod memo_transfer { diff --git a/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/tests/test_memo_transfer.rs b/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/tests/test_memo_transfer.rs new file mode 100644 index 000000000..85c85e8c9 --- /dev/null +++ b/tokens/token-2022/memo-transfer/anchor/programs/memo-transfer/tests/test_memo_transfer.rs @@ -0,0 +1,239 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + assert_token_account_balance, create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_mint, mint_tokens_to_token_extensions_account, + TOKEN_EXTENSIONS_PROGRAM_ID, + }, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn memo_program_id() -> Pubkey { + "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" + .parse() + .unwrap() +} + +/// Create a Token Extensions token account (165 bytes, no extra extensions). +/// Uses explicit keypair — not an ATA — because the test needs multiple +/// source accounts for the same owner+mint. +fn create_token_account_instructions( + payer: &Pubkey, + token_account: &Pubkey, + mint: &Pubkey, + owner: &Pubkey, +) -> Vec { + let rent_sysvar: Pubkey = "SysvarRent111111111111111111111111111111111" + .parse() + .unwrap(); + let create_ix = anchor_lang::solana_program::system_instruction::create_account( + payer, + token_account, + 3_000_000, + 165, + &TOKEN_EXTENSIONS_PROGRAM_ID, + ); + let init_ix = Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*token_account, false), + AccountMeta::new_readonly(*mint, false), + AccountMeta::new_readonly(*owner, false), + AccountMeta::new_readonly(rent_sysvar, false), + ], + data: vec![1], // InitializeAccount + }; + vec![create_ix, init_ix] +} + +/// Transfer instruction for Token Extensions (instruction 3). +fn transfer_instruction( + source: &Pubkey, + dest: &Pubkey, + authority: &Pubkey, + amount: u64, +) -> Instruction { + let mut data = vec![3u8]; + data.extend_from_slice(&amount.to_le_bytes()); + Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*source, false), + AccountMeta::new(*dest, false), + AccountMeta::new_readonly(*authority, true), + ], + data, + } +} + +/// Memo instruction: just the memo text as bytes. +fn memo_instruction(memo_text: &str, signers: &[&Pubkey]) -> Instruction { + let accounts: Vec = signers + .iter() + .map(|s| AccountMeta::new_readonly(**s, true)) + .collect(); + Instruction { + program_id: memo_program_id(), + accounts, + data: memo_text.as_bytes().to_vec(), + } +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = memo_transfer::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/memo_transfer.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + // Load SPL Memo program (needed for memo instructions) + let memo_program_bytes = include_bytes!("../../../tests/fixtures/spl_memo.so"); + svm.add_program(memo_program_id(), memo_program_bytes) + .unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_memo_transfer() { + let (mut svm, program_id, payer) = setup(); + let token_keypair = Keypair::new(); + + // Step 1: Create a standard Token Extensions mint (no extensions on the mint) + let mint = create_token_extensions_mint(&mut svm, &payer, 2, None, &[]).unwrap(); + svm.expire_blockhash(); + + // Step 2: Create token account with RequiredMemo extension via program + let initialize_ix = Instruction::new_with_bytes( + program_id, + &memo_transfer::instruction::Initialize {}.data(), + memo_transfer::accounts::Initialize { + payer: payer.pubkey(), + token_account: token_keypair.pubkey(), + mint_account: mint, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &token_keypair], &payer.pubkey()).unwrap(); + + // Verify token account exists + let token_account = svm + .get_account(&token_keypair.pubkey()) + .expect("Token account should exist"); + assert!( + !token_account.data.is_empty(), + "Token account should have data" + ); + + svm.expire_blockhash(); + + // Step 3: Create a source token account and mint tokens to it + let source_keypair = Keypair::new(); + let create_source_ixs = create_token_account_instructions( + &payer.pubkey(), + &source_keypair.pubkey(), + &mint, + &payer.pubkey(), + ); + send_transaction_from_instructions(&mut svm, create_source_ixs, &[&payer, &source_keypair], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + mint_tokens_to_token_extensions_account( + &mut svm, + &mint, + &source_keypair.pubkey(), + 100, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 4: Transfer without memo — should fail + let transfer_ix = transfer_instruction( + &source_keypair.pubkey(), + &token_keypair.pubkey(), + &payer.pubkey(), + 1, + ); + let result = send_transaction_from_instructions(&mut svm, vec![transfer_ix], &[&payer], &payer.pubkey()); + assert!( + result.is_err(), + "Transfer without memo should fail" + ); + svm.expire_blockhash(); + + // Step 5: Transfer with memo — should succeed + let memo_ix = memo_instruction("hello, world", &[&payer.pubkey()]); + let transfer_ix = transfer_instruction( + &source_keypair.pubkey(), + &token_keypair.pubkey(), + &payer.pubkey(), + 1, + ); + send_transaction_from_instructions(&mut svm, vec![memo_ix, transfer_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + assert_token_account_balance(&svm, &token_keypair.pubkey(), 1, "Should have 1 token after transfer with memo"); + + // Step 6: Disable RequiredMemo extension + let disable_ix = Instruction::new_with_bytes( + program_id, + &memo_transfer::instruction::Disable {}.data(), + memo_transfer::accounts::Disable { + owner: payer.pubkey(), + token_account: token_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![disable_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 7: Transfer without memo should now succeed (memo disabled) + let source2_keypair = Keypair::new(); + let create_source2_ixs = create_token_account_instructions( + &payer.pubkey(), + &source2_keypair.pubkey(), + &mint, + &payer.pubkey(), + ); + send_transaction_from_instructions(&mut svm, create_source2_ixs, &[&payer, &source2_keypair], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + mint_tokens_to_token_extensions_account( + &mut svm, + &mint, + &source2_keypair.pubkey(), + 100, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + let transfer_ix2 = transfer_instruction( + &source2_keypair.pubkey(), + &token_keypair.pubkey(), + &payer.pubkey(), + 1, + ); + send_transaction_from_instructions(&mut svm, vec![transfer_ix2], &[&payer], &payer.pubkey()).unwrap(); + + assert_token_account_balance( + &svm, + &token_keypair.pubkey(), + 2, + "Should have 2 tokens after transfer without memo (memo disabled)", + ); +} diff --git a/tokens/token-2022/memo-transfer/anchor/tests/fixtures/spl_memo.so b/tokens/token-2022/memo-transfer/anchor/tests/fixtures/spl_memo.so new file mode 100644 index 000000000..88385a01d Binary files /dev/null and b/tokens/token-2022/memo-transfer/anchor/tests/fixtures/spl_memo.so differ diff --git a/tokens/token-2022/memo-transfer/anchor/tests/memo-transfer.ts b/tokens/token-2022/memo-transfer/anchor/tests/memo-transfer.ts index 3a236ca14..5071464b0 100644 --- a/tokens/token-2022/memo-transfer/anchor/tests/memo-transfer.ts +++ b/tokens/token-2022/memo-transfer/anchor/tests/memo-transfer.ts @@ -1,11 +1,11 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { createMemoInstruction } from '@solana/spl-memo'; -import { createAccount, createMint, createTransferInstruction, mintTo, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import { sendAndConfirmTransaction, Transaction } from '@solana/web3.js'; -import type { MemoTransfer } from '../target/types/memo_transfer'; - -describe('memo-transfer', () => { +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { createMemoInstruction } from "@solana/spl-memo"; +import { createAccount, createMint, createTransferInstruction, mintTo, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import { sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; +import type { MemoTransfer } from "../target/types/memo_transfer"; + +describe("memo-transfer", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); const connection = provider.connection; @@ -17,7 +17,7 @@ describe('memo-transfer', () => { const mintKeypair = new anchor.web3.Keypair(); const tokenKeypair = new anchor.web3.Keypair(); - it('Create Token Account with RequiredMemo extension', async () => { + it("Create Token Account with RequiredMemo extension", async () => { await createMint( connection, wallet.payer, // Payer of the transaction and initialization fees @@ -37,10 +37,10 @@ describe('memo-transfer', () => { }) .signers([tokenKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Attempt transfer without memo, expect fail', async () => { + it("Attempt transfer without memo, expect fail", async () => { // Create a new token account to transfer to const sourceTokenAccount = await createAccount( connection, @@ -52,7 +52,17 @@ describe('memo-transfer', () => { TOKEN_2022_PROGRAM_ID, // Token Extension Program ID ); - await mintTo(connection, wallet.payer, mintKeypair.publicKey, sourceTokenAccount, wallet.payer, 1, [], null, TOKEN_2022_PROGRAM_ID); + await mintTo( + connection, + wallet.payer, + mintKeypair.publicKey, + sourceTokenAccount, + wallet.payer, + 1, + [], + null, + TOKEN_2022_PROGRAM_ID, + ); const transferInstruction = createTransferInstruction( sourceTokenAccount, // Source Token Account @@ -73,11 +83,11 @@ describe('memo-transfer', () => { [wallet.payer], // Signers ); } catch (error) { - console.log('\nExpect Error:', error.logs); + console.log("\nExpect Error:", error.logs); } }); - it('Attempt transfer with memo, expect success', async () => { + it("Attempt transfer with memo, expect success", async () => { // Create a new token account to transfer to const sourceTokenAccount = await createAccount( connection, @@ -89,9 +99,19 @@ describe('memo-transfer', () => { TOKEN_2022_PROGRAM_ID, // Token Extension Program ID ); - await mintTo(connection, wallet.payer, mintKeypair.publicKey, sourceTokenAccount, wallet.payer, 1, [], null, TOKEN_2022_PROGRAM_ID); + await mintTo( + connection, + wallet.payer, + mintKeypair.publicKey, + sourceTokenAccount, + wallet.payer, + 1, + [], + null, + TOKEN_2022_PROGRAM_ID, + ); - const memoInstruction = createMemoInstruction('hello, world', [wallet.publicKey]); + const memoInstruction = createMemoInstruction("hello, world", [wallet.publicKey]); const transferInstruction = createTransferInstruction( sourceTokenAccount, // Source Token Account @@ -110,20 +130,20 @@ describe('memo-transfer', () => { [wallet.payer], // Signers ); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Disable RequiredMemo extension', async () => { + it("Disable RequiredMemo extension", async () => { const transactionSignature = await program.methods .disable() .accounts({ tokenAccount: tokenKeypair.publicKey, }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Attempt transfer without memo, expect success', async () => { + it("Attempt transfer without memo, expect success", async () => { // Create a new token account to transfer to const sourceTokenAccount = await createAccount( connection, @@ -135,7 +155,17 @@ describe('memo-transfer', () => { TOKEN_2022_PROGRAM_ID, // Token Extension Program ID ); - await mintTo(connection, wallet.payer, mintKeypair.publicKey, sourceTokenAccount, wallet.payer, 1, [], null, TOKEN_2022_PROGRAM_ID); + await mintTo( + connection, + wallet.payer, + mintKeypair.publicKey, + sourceTokenAccount, + wallet.payer, + 1, + [], + null, + TOKEN_2022_PROGRAM_ID, + ); const transferInstruction = createTransferInstruction( sourceTokenAccount, // Source Token Account @@ -154,6 +184,6 @@ describe('memo-transfer', () => { [wallet.payer], // Signers ); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); }); diff --git a/tokens/token-2022/metadata/anchor/Anchor.toml b/tokens/token-2022/metadata/anchor/Anchor.toml index 539f4bdb8..55e77777e 100644 --- a/tokens/token-2022/metadata/anchor/Anchor.toml +++ b/tokens/token-2022/metadata/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -metadata = "BJHEDXSQfD9kBFvhw8ZCGmPFRihzvbMoxoHUKpXdpn4D" - -# [registry] section removed — no longer used in Anchor 1.0 +metadata = "DY2T6zhjngLvpkCMReQFzMHc6g4d4bqQWznntroEVDhG" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/metadata/anchor/migrations/deploy.ts b/tokens/token-2022/metadata/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/metadata/anchor/migrations/deploy.ts +++ b/tokens/token-2022/metadata/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/metadata/anchor/package.json b/tokens/token-2022/metadata/anchor/package.json index 95288be45..f209d0891 100644 --- a/tokens/token-2022/metadata/anchor/package.json +++ b/tokens/token-2022/metadata/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token-metadata": "^0.1.4" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token-metadata": "^0.1.4" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/metadata/anchor/pnpm-lock.yaml b/tokens/token-2022/metadata/anchor/pnpm-lock.yaml index 733244d50..ac2c534ed 100644 --- a/tokens/token-2022/metadata/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/metadata/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token-metadata': specifier: ^0.1.4 version: 0.1.4(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -753,16 +753,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -780,7 +780,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/token-2022/metadata/anchor/programs/metadata/Cargo.toml b/tokens/token-2022/metadata/anchor/programs/metadata/Cargo.toml index 52389758d..306c196bc 100644 --- a/tokens/token-2022/metadata/anchor/programs/metadata/Cargo.toml +++ b/tokens/token-2022/metadata/anchor/programs/metadata/Cargo.toml @@ -20,10 +20,18 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -spl-token-metadata-interface = "0.3.3" -spl-type-length-value = "0.4.3" +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" +# Updated from 0.3.3/0.4.3 — old versions pulled in broken solana-zk-token-sdk transitive deps +spl-token-metadata-interface = "0.8.0" +spl-type-length-value = "0.9.1" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/initialize.rs b/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/initialize.rs index f657138d1..a482bd4f9 100644 --- a/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/initialize.rs +++ b/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/initialize.rs @@ -1,7 +1,8 @@ use anchor_lang::prelude::*; -use anchor_lang::solana_program::rent::{ - DEFAULT_EXEMPTION_THRESHOLD, DEFAULT_LAMPORTS_PER_BYTE_YEAR, -}; +// DEFAULT_EXEMPTION_THRESHOLD=2.0 years, DEFAULT_LAMPORTS_PER_BYTE_YEAR=3480 +// These constants were removed from public API in newer Solana versions +const DEFAULT_LAMPORTS_PER_BYTE_YEAR: u64 = 3480; +const DEFAULT_EXEMPTION_THRESHOLD: f64 = 2.0; use anchor_lang::system_program::{transfer, Transfer}; use anchor_spl::token_interface::{ token_metadata_initialize, Mint, Token2022, TokenMetadataInitialize, @@ -62,7 +63,7 @@ pub fn process_initialize(ctx: Context, args: TokenMetadataArgs) -> CpiContext::new( ctx.accounts.token_program.key(), TokenMetadataInitialize { - token_program_id: ctx.accounts.token_program.to_account_info(), + program_id: ctx.accounts.token_program.to_account_info(), mint: ctx.accounts.mint_account.to_account_info(), metadata: ctx.accounts.mint_account.to_account_info(), mint_authority: ctx.accounts.payer.to_account_info(), diff --git a/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_authority.rs b/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_authority.rs index 994712325..f68b619a7 100644 --- a/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_authority.rs +++ b/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_authority.rs @@ -29,7 +29,7 @@ pub fn process_update_authority(ctx: Context) -> Result<()> { CpiContext::new( ctx.accounts.token_program.key(), TokenMetadataUpdateAuthority { - token_program_id: ctx.accounts.token_program.to_account_info(), + program_id: ctx.accounts.token_program.to_account_info(), metadata: ctx.accounts.mint_account.to_account_info(), current_authority: ctx.accounts.current_authority.to_account_info(), diff --git a/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_field.rs b/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_field.rs index 2e94c7b1c..adb20b8f2 100644 --- a/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_field.rs +++ b/tokens/token-2022/metadata/anchor/programs/metadata/src/instructions/update_field.rs @@ -80,7 +80,7 @@ pub fn process_update_field(ctx: Context, args: UpdateFieldArgs) -> CpiContext::new( ctx.accounts.token_program.key(), TokenMetadataUpdateField { - token_program_id: ctx.accounts.token_program.to_account_info(), + program_id: ctx.accounts.token_program.to_account_info(), metadata: ctx.accounts.mint_account.to_account_info(), update_authority: ctx.accounts.authority.to_account_info(), }, diff --git a/tokens/token-2022/metadata/anchor/programs/metadata/src/lib.rs b/tokens/token-2022/metadata/anchor/programs/metadata/src/lib.rs index c543cd324..590302b61 100644 --- a/tokens/token-2022/metadata/anchor/programs/metadata/src/lib.rs +++ b/tokens/token-2022/metadata/anchor/programs/metadata/src/lib.rs @@ -1,9 +1,9 @@ use anchor_lang::prelude::*; use instructions::*; -mod instructions; +pub mod instructions; -declare_id!("BJHEDXSQfD9kBFvhw8ZCGmPFRihzvbMoxoHUKpXdpn4D"); +declare_id!("DY2T6zhjngLvpkCMReQFzMHc6g4d4bqQWznntroEVDhG"); #[program] pub mod metadata { diff --git a/tokens/token-2022/metadata/anchor/programs/metadata/tests/test_metadata.rs b/tokens/token-2022/metadata/anchor/programs/metadata/tests/test_metadata.rs new file mode 100644 index 000000000..5ed4c5ce9 --- /dev/null +++ b/tokens/token-2022/metadata/anchor/programs/metadata/tests/test_metadata.rs @@ -0,0 +1,156 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::TOKEN_EXTENSIONS_PROGRAM_ID, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = metadata::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/metadata.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_metadata_full_flow() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + + // Step 1: Initialize mint with MetadataPointer and TokenMetadata extensions + let initialize_ix = Instruction::new_with_bytes( + program_id, + &metadata::instruction::Initialize { + args: metadata::instructions::TokenMetadataArgs { + name: "OPOS".to_string(), + symbol: "OPOS".to_string(), + uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json".to_string(), + }, + } + .data(), + metadata::accounts::Initialize { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); + + // Verify mint exists + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should exist"); + assert!(!mint_account.data.is_empty(), "Mint should have data"); + + svm.expire_blockhash(); + + // Step 2: Update existing metadata field (name) + let update_name_ix = Instruction::new_with_bytes( + program_id, + &metadata::instruction::UpdateField { + args: metadata::instructions::UpdateFieldArgs { + field: metadata::instructions::AnchorField::Name, + value: "Solana".to_string(), + }, + } + .data(), + metadata::accounts::UpdateField { + authority: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![update_name_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 3: Add custom field + let add_custom_field_ix = Instruction::new_with_bytes( + program_id, + &metadata::instruction::UpdateField { + args: metadata::instructions::UpdateFieldArgs { + field: metadata::instructions::AnchorField::Key("color".to_string()), + value: "red".to_string(), + }, + } + .data(), + metadata::accounts::UpdateField { + authority: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![add_custom_field_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 4: Remove custom field + let remove_key_ix = Instruction::new_with_bytes( + program_id, + &metadata::instruction::RemoveKey { + key: "color".to_string(), + } + .data(), + metadata::accounts::RemoveKey { + update_authority: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![remove_key_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 5: Update authority to None + let update_authority_ix = Instruction::new_with_bytes( + program_id, + &metadata::instruction::UpdateAuthority {}.data(), + metadata::accounts::UpdateAuthority { + current_authority: payer.pubkey(), + new_authority: None, + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![update_authority_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 6: Emit metadata (verify it doesn't fail) + let emit_ix = Instruction::new_with_bytes( + program_id, + &metadata::instruction::Emit {}.data(), + metadata::accounts::Emit { + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![emit_ix], &[&payer], &payer.pubkey()).unwrap(); + + // Verify mint still exists after all operations + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should still exist after all metadata operations"); + assert!( + !mint_account.data.is_empty(), + "Mint should still have data" + ); +} diff --git a/tokens/token-2022/metadata/anchor/tests/metadata.ts b/tokens/token-2022/metadata/anchor/tests/metadata.ts index c788bd0f9..b88a03944 100644 --- a/tokens/token-2022/metadata/anchor/tests/metadata.ts +++ b/tokens/token-2022/metadata/anchor/tests/metadata.ts @@ -1,9 +1,9 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { unpack } from '@solana/spl-token-metadata'; -import type { Metadata } from '../target/types/metadata'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { unpack } from "@solana/spl-token-metadata"; +import type { Metadata } from "../target/types/metadata"; -describe('metadata', () => { +describe("metadata", () => { const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); @@ -12,52 +12,52 @@ describe('metadata', () => { const mintKeypair = new anchor.web3.Keypair(); const metadata = { - name: 'OPOS', - symbol: 'OPOS', - uri: 'https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json', + name: "OPOS", + symbol: "OPOS", + uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json", }; - it('Create Mint with MetadataPointer and TokenMetadata Extensions', async () => { + it("Create Mint with MetadataPointer and TokenMetadata Extensions", async () => { const tx = await program.methods .initialize(metadata) .accounts({ mintAccount: mintKeypair.publicKey }) .signers([mintKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', tx); + console.log("Your transaction signature", tx); }); - it('Update existing metadata field', async () => { + it("Update existing metadata field", async () => { // Add your test here. const tx = await program.methods .updateField({ field: { name: {} }, // Update the name field - value: 'Solana', + value: "Solana", }) .accounts({ mintAccount: mintKeypair.publicKey }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', tx); + console.log("Your transaction signature", tx); }); - it('Update metadata with custom field', async () => { + it("Update metadata with custom field", async () => { const tx = await program.methods .updateField({ - field: { key: { 0: 'color' } }, // Add a custom field named "color" - value: 'red', + field: { key: { 0: "color" } }, // Add a custom field named "color" + value: "red", }) .accounts({ mintAccount: mintKeypair.publicKey }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', tx); + console.log("Your transaction signature", tx); }); - it('Remove custom field', async () => { + it("Remove custom field", async () => { const tx = await program.methods - .removeKey('color') // Remove the custom field named "color" + .removeKey("color") // Remove the custom field named "color" .accounts({ mintAccount: mintKeypair.publicKey }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', tx); + console.log("Your transaction signature", tx); }); - it('Change update authority', async () => { + it("Change update authority", async () => { const tx = await program.methods .updateAuthority() .accounts({ @@ -65,45 +65,45 @@ describe('metadata', () => { newAuthority: null, // Set the update authority to null }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', tx); + console.log("Your transaction signature", tx); }); - it('Emit metadata, decode transaction logs', async () => { + it("Emit metadata, decode transaction logs", async () => { const txSignature = await program.methods .emit() .accounts({ mintAccount: mintKeypair.publicKey }) - .rpc({ commitment: 'confirmed', skipPreflight: true }); - console.log('Your transaction signature', txSignature); + .rpc({ commitment: "confirmed", skipPreflight: true }); + console.log("Your transaction signature", txSignature); // Fetch the transaction response const transactionResponse = await provider.connection.getTransaction(txSignature, { - commitment: 'confirmed', + commitment: "confirmed", }); // Extract the log message that starts with "Program return:" - const prefix = 'Program return: '; + const prefix = "Program return: "; let log = transactionResponse.meta.logMessages.find((log) => log.startsWith(prefix)); log = log.slice(prefix.length); - const [_, data] = log.split(' ', 2); + const [_, data] = log.split(" ", 2); // Decode the data from base64 and unpack it into TokenMetadata - const buffer = Buffer.from(data, 'base64'); + const buffer = Buffer.from(data, "base64"); const metadata = unpack(buffer); - console.log('Metadata', metadata); + console.log("Metadata", metadata); }); - it('Emit metadata, decode simulated transaction', async () => { + it("Emit metadata, decode simulated transaction", async () => { const simulateResponse = await program.methods.emit().accounts({ mintAccount: mintKeypair.publicKey }).simulate(); // Extract the log message that starts with "Program return:" - const prefix = 'Program return: '; + const prefix = "Program return: "; let log = simulateResponse.raw.find((log) => log.startsWith(prefix)); log = log.slice(prefix.length); - const [_, data] = log.split(' ', 2); + const [_, data] = log.split(" ", 2); // Decode the data from base64 and unpack it into TokenMetadata - const buffer = Buffer.from(data, 'base64'); + const buffer = Buffer.from(data, "base64"); const metadata = unpack(buffer); - console.log('Metadata', metadata); + console.log("Metadata", metadata); }); }); diff --git a/tokens/token-2022/mint-close-authority/anchor/Anchor.toml b/tokens/token-2022/mint-close-authority/anchor/Anchor.toml index 0f826c9c0..2abc42bff 100644 --- a/tokens/token-2022/mint-close-authority/anchor/Anchor.toml +++ b/tokens/token-2022/mint-close-authority/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -mint_close_authority = "AcfQLsYKuzprcCNH1n96pKKgAbAnZchwpbr3gbVN742n" - -# [registry] section removed — no longer used in Anchor 1.0 +mint_close_authority = "2wT6WQQqD4P35mDQJAWbWAMzFfCeLsYEELTde6jLQyKN" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/mint-close-authority/anchor/migrations/deploy.ts b/tokens/token-2022/mint-close-authority/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/mint-close-authority/anchor/migrations/deploy.ts +++ b/tokens/token-2022/mint-close-authority/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/mint-close-authority/anchor/package.json b/tokens/token-2022/mint-close-authority/anchor/package.json index f800607c4..cc320fb64 100644 --- a/tokens/token-2022/mint-close-authority/anchor/package.json +++ b/tokens/token-2022/mint-close-authority/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/mint-close-authority/anchor/pnpm-lock.yaml b/tokens/token-2022/mint-close-authority/anchor/pnpm-lock.yaml index 841b2d24e..349da1833 100644 --- a/tokens/token-2022/mint-close-authority/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/mint-close-authority/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.6 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -860,16 +860,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -887,7 +887,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/Cargo.toml b/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/Cargo.toml index 685accde4..e97b9f2be 100644 --- a/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/Cargo.toml +++ b/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/Cargo.toml @@ -17,5 +17,12 @@ no-log-ix-name = [] idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] [dependencies] -anchor-lang = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" diff --git a/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/src/lib.rs b/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/src/lib.rs index 3be5a5390..8cda7fade 100644 --- a/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/src/lib.rs +++ b/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/src/lib.rs @@ -13,7 +13,7 @@ use anchor_spl::{ Mint, Token2022, }, }; -declare_id!("AcfQLsYKuzprcCNH1n96pKKgAbAnZchwpbr3gbVN742n"); +declare_id!("2wT6WQQqD4P35mDQJAWbWAMzFfCeLsYEELTde6jLQyKN"); #[program] pub mod mint_close_authority { diff --git a/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/tests/test_mint_close_authority.rs b/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/tests/test_mint_close_authority.rs new file mode 100644 index 000000000..2530914f9 --- /dev/null +++ b/tokens/token-2022/mint-close-authority/anchor/programs/mint-close-authority/tests/test_mint_close_authority.rs @@ -0,0 +1,127 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::TOKEN_EXTENSIONS_PROGRAM_ID, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = mint_close_authority::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/mint_close_authority.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_create_and_close_mint() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + + // Step 1: Create Mint with Close Authority + let initialize_ix = Instruction::new_with_bytes( + program_id, + &mint_close_authority::instruction::Initialize {}.data(), + mint_close_authority::accounts::Initialize { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); + + // Verify mint exists + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should exist"); + assert!(!mint_account.data.is_empty(), "Mint should have data"); + + svm.expire_blockhash(); + + // Step 2: Close Mint using Anchor CPI + let close_ix = Instruction::new_with_bytes( + program_id, + &mint_close_authority::instruction::Close {}.data(), + mint_close_authority::accounts::Close { + authority: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![close_ix], &[&payer], &payer.pubkey()).unwrap(); + + // Verify mint no longer exists (lamports returned to authority) + let mint_account = svm.get_account(&mint_keypair.pubkey()); + assert!( + mint_account.is_none(), + "Mint account should be closed" + ); + + svm.expire_blockhash(); + + // Step 3: Create Mint with Close Authority again (re-use same keypair) + let initialize_ix2 = Instruction::new_with_bytes( + program_id, + &mint_close_authority::instruction::Initialize {}.data(), + mint_close_authority::accounts::Initialize { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix2], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); + + // Verify mint exists again + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should exist after re-creation"); + assert!( + !mint_account.data.is_empty(), + "Mint should have data after re-creation" + ); + + svm.expire_blockhash(); + + // Step 4: Close Mint directly using Token Extensions CloseAccount instruction + let close_direct_ix = Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + anchor_lang::solana_program::instruction::AccountMeta::new( + mint_keypair.pubkey(), + false, + ), + anchor_lang::solana_program::instruction::AccountMeta::new( + payer.pubkey(), + false, + ), + anchor_lang::solana_program::instruction::AccountMeta::new_readonly( + payer.pubkey(), + true, + ), + ], + data: vec![9], // CloseAccount + }; + send_transaction_from_instructions(&mut svm, vec![close_direct_ix], &[&payer], &payer.pubkey()).unwrap(); + + // Verify mint is closed again + let mint_account = svm.get_account(&mint_keypair.pubkey()); + assert!( + mint_account.is_none(), + "Mint account should be closed via direct Token Extensions instruction" + ); +} diff --git a/tokens/token-2022/mint-close-authority/anchor/tests/mint-close-authority.ts b/tokens/token-2022/mint-close-authority/anchor/tests/mint-close-authority.ts index 73b08722a..05d1bc7a5 100644 --- a/tokens/token-2022/mint-close-authority/anchor/tests/mint-close-authority.ts +++ b/tokens/token-2022/mint-close-authority/anchor/tests/mint-close-authority.ts @@ -1,9 +1,9 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { closeAccount, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import type { MintCloseAuthority } from '../target/types/mint_close_authority'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { closeAccount, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import type { MintCloseAuthority } from "../target/types/mint_close_authority"; -describe('mint-close-authority', () => { +describe("mint-close-authority", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); const connection = provider.connection; @@ -14,30 +14,33 @@ describe('mint-close-authority', () => { const mintKeypair = new anchor.web3.Keypair(); - it('Create Mint with Close Authority', async () => { + it("Create Mint with Close Authority", async () => { const transactionSignature = await program.methods .initialize() .accounts({ mintAccount: mintKeypair.publicKey }) .signers([mintKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Close Mint with Anchor CPI', async () => { - const transactionSignature = await program.methods.close().accounts({ mintAccount: mintKeypair.publicKey }).rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + it("Close Mint with Anchor CPI", async () => { + const transactionSignature = await program.methods + .close() + .accounts({ mintAccount: mintKeypair.publicKey }) + .rpc({ skipPreflight: true }); + console.log("Your transaction signature", transactionSignature); }); - it('Create Mint with Close Authority again', async () => { + it("Create Mint with Close Authority again", async () => { const transactionSignature = await program.methods .initialize() .accounts({ mintAccount: mintKeypair.publicKey }) .signers([mintKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Close Mint using @solana/spl-token', async () => { + it("Close Mint using @solana/spl-token", async () => { const transactionSignature = await closeAccount( connection, wallet.payer, // Transaction fee payer @@ -48,6 +51,6 @@ describe('mint-close-authority', () => { undefined, // Confirmation options TOKEN_2022_PROGRAM_ID, // Token Extension Program ID ); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); }); diff --git a/tokens/token-2022/mint-close-authority/native/tests/test.ts b/tokens/token-2022/mint-close-authority/native/tests/test.ts index 8d4ce50f2..822c359df 100644 --- a/tokens/token-2022/mint-close-authority/native/tests/test.ts +++ b/tokens/token-2022/mint-close-authority/native/tests/test.ts @@ -1,24 +1,30 @@ -import { Buffer } from 'node:buffer'; -import { describe, test } from 'node:test'; -import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import { Keypair, PublicKey, SYSVAR_RENT_PUBKEY, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { assert } from 'chai'; -import { start } from 'solana-bankrun'; +import { Buffer } from "node:buffer"; +import { describe, test } from "node:test"; +import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import { + Keypair, + PublicKey, + SYSVAR_RENT_PUBKEY, + SystemProgram, + Transaction, + TransactionInstruction, +} from "@solana/web3.js"; +import * as borsh from "borsh"; +import { assert } from "chai"; +import { start } from "solana-bankrun"; - -const CreateTokenArgsSchema = { struct: { token_decimals: 'u8' } }; +const CreateTokenArgsSchema = { struct: { token_decimals: "u8" } }; function borshSerialize(schema: borsh.Schema, data: object): Buffer { return Buffer.from(borsh.serialize(schema, data)); } -describe('Create Token', async () => { +describe("Create Token", async () => { const PROGRAM_ID = PublicKey.unique(); const context = await start( [ { - name: 'token_2022_mint_close_authority_program', + name: "token_2022_mint_close_authority_program", programId: PROGRAM_ID, }, ], @@ -27,7 +33,7 @@ describe('Create Token', async () => { const client = context.banksClient; const payer = context.payer; - test('Create a Token-22 SPL-Token !', async () => { + test("Create a Token-22 SPL-Token !", async () => { const mintKeypair: Keypair = Keypair.generate(); const instructionData = borshSerialize(CreateTokenArgsSchema, { @@ -56,6 +62,6 @@ describe('Create Token', async () => { const transaction = await client.processTransaction(tx); assert(transaction.logMessages[0].startsWith(`Program ${PROGRAM_ID}`)); - console.log('Token Mint Address: ', mintKeypair.publicKey.toBase58()); + console.log("Token Mint Address: ", mintKeypair.publicKey.toBase58()); }); }); diff --git a/tokens/token-2022/multiple-extensions/native/tests/test.ts b/tokens/token-2022/multiple-extensions/native/tests/test.ts index 94757d648..f5b165793 100644 --- a/tokens/token-2022/multiple-extensions/native/tests/test.ts +++ b/tokens/token-2022/multiple-extensions/native/tests/test.ts @@ -1,25 +1,31 @@ -import { Buffer } from 'node:buffer'; -import { describe, test } from 'node:test'; -import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import { Keypair, PublicKey, SYSVAR_RENT_PUBKEY, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { assert } from 'chai'; -import { start } from 'solana-bankrun'; - - -const CreateTokenArgsSchema = { struct: { token_decimals: 'u8' } }; +import { Buffer } from "node:buffer"; +import { describe, test } from "node:test"; +import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import { + Keypair, + PublicKey, + SYSVAR_RENT_PUBKEY, + SystemProgram, + Transaction, + TransactionInstruction, +} from "@solana/web3.js"; +import * as borsh from "borsh"; +import { assert } from "chai"; +import { start } from "solana-bankrun"; + +const CreateTokenArgsSchema = { struct: { token_decimals: "u8" } }; function borshSerialize(schema: borsh.Schema, data: object): Buffer { return Buffer.from(borsh.serialize(schema, data)); } -describe('Create Token', async () => { +describe("Create Token", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'token_2022_multiple_extensions_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "token_2022_multiple_extensions_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; - test('Create a Token-22 SPL-Token !', async () => { + test("Create a Token-22 SPL-Token !", async () => { const blockhash = context.lastBlockhash; const mintKeypair: Keypair = Keypair.generate(); @@ -48,6 +54,6 @@ describe('Create Token', async () => { const transaction = await client.processTransaction(tx); assert(transaction.logMessages[0].startsWith(`Program ${PROGRAM_ID}`)); - console.log('Token Mint Address: ', mintKeypair.publicKey.toBase58()); + console.log("Token Mint Address: ", mintKeypair.publicKey.toBase58()); }); }); diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/Anchor.toml b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/Anchor.toml index 4d5cc7caf..e456b3fb2 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/Anchor.toml +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/Anchor.toml @@ -2,12 +2,11 @@ solana_version = "3.1.8" [features] -seeds = false -[programs.localnet] -extension_nft = "9aZZ7TJ2fQZxY8hMtWXywp5y6BgqC4N2BPcr9FDT47sW" +resolution = true +skip-lint = false -[registry] -url = "https://anchor.projectserum.com" +[programs.localnet] +extension_nft = "EUMxHm5RdorS96YVEh1SwhacqhWyKTRoaRezUZuhBBzN" [provider] cluster = "localnet" @@ -15,3 +14,5 @@ wallet = "~/.config/solana/id.json" [scripts] test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" + +[hooks] diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/migrations/deploy.ts b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/migrations/deploy.ts index 0a1222c93..20e6e1c1b 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/migrations/deploy.ts +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@project-serum/anchor'); +const anchor = require("@project-serum/anchor"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/package.json b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/package.json index 691d96bb6..3763466c1 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/package.json +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/package.json @@ -1,24 +1,24 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@coral-xyz/spl-token": "0.30.0", - "@solana/spl-token": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "browserify-sign": ">=4.2.2", - "chai": "^4.3.4", - "crypto-js": ">=4.2.0", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^4.3.5" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@coral-xyz/spl-token": "0.30.0", + "@solana/spl-token": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "browserify-sign": ">=4.2.2", + "chai": "^4.3.4", + "crypto-js": ">=4.2.0", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^4.3.5" + } } diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/pnpm-lock.yaml b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/pnpm-lock.yaml index e9f9bc3a7..a3ab4efcf 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10) '@coral-xyz/spl-token': specifier: 0.30.0 version: 0.30.0(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10) @@ -51,18 +51,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.6': @@ -1004,16 +1004,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@4.9.5)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -1031,7 +1031,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.6': dependencies: diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/programs/extension_nft/Cargo.toml b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/programs/extension_nft/Cargo.toml index 2456842a5..3549014b5 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/programs/extension_nft/Cargo.toml +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/programs/extension_nft/Cargo.toml @@ -21,10 +21,10 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } -anchor-spl = { version = "1.0.0-rc.5" } -# session-keys pinned to 2.0.3 — check compatibility with Anchor 1.0/Solana 3.x +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = { version = "1.0.0" } +# session-keys pinned to 2.0.3 — NOT compatible with Anchor 1.0/Solana 3.x +# Program cannot build until session-keys releases an Anchor 1.0-compatible version session-keys = { version = "2.0.3", features = ["no-entrypoint"] } # Removed solana-program pin (=2.1.15) — Anchor 1.0 requires Solana 3.x deps spl-token-2022 = { version="6", features = [ "no-entrypoint" ] } diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/programs/extension_nft/src/lib.rs b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/programs/extension_nft/src/lib.rs index cd5637f76..194befcc7 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/programs/extension_nft/src/lib.rs +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/programs/extension_nft/src/lib.rs @@ -7,7 +7,7 @@ pub mod instructions; pub mod state; use instructions::*; -declare_id!("9aZZ7TJ2fQZxY8hMtWXywp5y6BgqC4N2BPcr9FDT47sW"); +declare_id!("EUMxHm5RdorS96YVEh1SwhacqhWyKTRoaRezUZuhBBzN"); #[program] pub mod extension_nft { diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/tests/lumberjack.ts b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/tests/lumberjack.ts index bbba9941f..ebb22db4e 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/tests/lumberjack.ts +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/anchor/tests/lumberjack.ts @@ -1,30 +1,30 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, getOrCreateAssociatedTokenAccount, TOKEN_2022_PROGRAM_ID, -} from '@solana/spl-token'; -import { Keypair } from '@solana/web3.js'; -import type { ExtensionNft } from '../target/types/extension_nft'; +} from "@solana/spl-token"; +import { Keypair } from "@solana/web3.js"; +import type { ExtensionNft } from "../target/types/extension_nft"; -describe('extension_nft', () => { +describe("extension_nft", () => { const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); const program = anchor.workspace.ExtensionNft as Program; const payer = provider.wallet as anchor.Wallet; - it('Mint nft!', async () => { + it("Mint nft!", async () => { const balance = await anchor.getProvider().connection.getBalance(payer.publicKey); if (balance < 1e8) { const res = await anchor.getProvider().connection.requestAirdrop(payer.publicKey, 1e9); - await anchor.getProvider().connection.confirmTransaction(res, 'confirmed'); + await anchor.getProvider().connection.confirmTransaction(res, "confirmed"); } const mint = new Keypair(); - console.log('Mint public key', mint.publicKey.toBase58()); + console.log("Mint public key", mint.publicKey.toBase58()); const destinationTokenAccount = getAssociatedTokenAddressSync( mint.publicKey, @@ -45,7 +45,7 @@ describe('extension_nft', () => { .signers([mint]) .rpc(); - console.log('Mint nft tx', tx); - await anchor.getProvider().connection.confirmTransaction(tx, 'confirmed'); + console.log("Mint nft tx", tx); + await anchor.getProvider().connection.confirmTransaction(tx, "confirmed"); }); }); diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/ChopTreeButton.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/ChopTreeButton.tsx index 4e3aefb1e..be58a2616 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/ChopTreeButton.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/ChopTreeButton.tsx @@ -1,40 +1,37 @@ -import Image from "next/image" -import { useCallback, useState } from "react" -import { Button, HStack, VStack } from "@chakra-ui/react" -import { useConnection, useWallet } from "@solana/wallet-adapter-react" -import { useSessionWallet } from "@magicblock-labs/gum-react-sdk" -import { useGameState } from "@/contexts/GameStateProvider" -import { GAME_DATA_SEED, gameDataPDA, program } from "@/utils/anchor" -import { PublicKey } from "@solana/web3.js" -import { useNftState } from "@/contexts/NftProvider" -import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token" +import { Button, HStack, VStack } from "@chakra-ui/react"; +import { useSessionWallet } from "@magicblock-labs/gum-react-sdk"; +import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import { useConnection, useWallet } from "@solana/wallet-adapter-react"; +import { PublicKey } from "@solana/web3.js"; +import Image from "next/image"; +import { useCallback, useState } from "react"; +import { useGameState } from "@/contexts/GameStateProvider"; +import { useNftState } from "@/contexts/NftProvider"; +import { GAME_DATA_SEED, gameDataPDA, program } from "@/utils/anchor"; const ChopTreeButton = () => { - const { publicKey, sendTransaction } = useWallet() - const { connection } = useConnection() - const sessionWallet = useSessionWallet() - const { gameState, playerDataPDA } = useGameState() - const [isLoadingSession, setIsLoadingSession] = useState(false) - const [isLoadingMainWallet, setIsLoadingMainWallet] = useState(false) - const [transactionCounter, setTransactionCounter] = useState(0) - const { nftState: nftState } = useNftState() + const { publicKey, sendTransaction } = useWallet(); + const { connection } = useConnection(); + const sessionWallet = useSessionWallet(); + const { gameState, playerDataPDA } = useGameState(); + const [isLoadingSession, setIsLoadingSession] = useState(false); + const [isLoadingMainWallet, setIsLoadingMainWallet] = useState(false); + const [transactionCounter, setTransactionCounter] = useState(0); + const { nftState } = useNftState(); const onChopClick = useCallback(async () => { - setIsLoadingSession(true) - if (!playerDataPDA || !sessionWallet) return + setIsLoadingSession(true); + if (!playerDataPDA || !sessionWallet?.publicKey) return; setTransactionCounter(transactionCounter + 1); - const nftAuthority = await PublicKey.findProgramAddress( - [Buffer.from("nft_authority")], - program.programId - ); + const nftAuthority = await PublicKey.findProgramAddress([Buffer.from("nft_authority")], program.programId); let nft = null; - - for (var i = 0; i < nftState.items.length; i++) { + + for (let i = 0; i < nftState.items.length; i++) { try { const nftData = nftState.items[i]; - if (nftData.authorities[0] == nftAuthority[0].toBase58()) { + if (nftData.authorities[0] === nftAuthority[0].toBase58()) { nft = nftData; } console.log("NFT data", nftData); @@ -56,35 +53,32 @@ const ChopTreeButton = () => { .accounts({ player: playerDataPDA, gameData: gameDataPDA, - signer: sessionWallet.publicKey!, + signer: sessionWallet.publicKey, sessionToken: sessionWallet.sessionToken, nftAuthority: nftAuthority[0], mint: nft.id, }) - .transaction() + .transaction(); - const txids = await sessionWallet.signAndSendTransaction!(transaction) + const txids = await sessionWallet.signAndSendTransaction?.(transaction); if (txids && txids.length > 0) { - console.log("Transaction sent:", txids) + console.log("Transaction sent:", txids); } else { - console.error("Failed to send transaction") + console.error("Failed to send transaction"); } - } catch (error: any) { - console.log("error", `Chopping failed! ${error?.message}`) + } catch (error) { + console.log("error", `Chopping failed! ${error instanceof Error ? error.message : String(error)}`); } finally { - setIsLoadingSession(false) + setIsLoadingSession(false); } - }, [sessionWallet, nftState]) + }, [sessionWallet, nftState, playerDataPDA, transactionCounter]); const onChopMainWalletClick = useCallback(async () => { - if (!publicKey || !playerDataPDA) return + if (!publicKey || !playerDataPDA) return; - setIsLoadingMainWallet(true) - const nftAuthority = await PublicKey.findProgramAddress( - [Buffer.from("nft_authority")], - program.programId - ); + setIsLoadingMainWallet(true); + const nftAuthority = await PublicKey.findProgramAddress([Buffer.from("nft_authority")], program.programId); if (nftState == null) { window.alert("Load NFT state first"); @@ -94,11 +88,11 @@ const ChopTreeButton = () => { console.log("NFT state", nftState); let nft = null; - for (var i = 0; i < nftState.items.length; i++) { + for (let i = 0; i < nftState.items.length; i++) { try { const nftData = nftState.items[i]; - console.log(nftData.authorities[0].address + " == " + nftAuthority[0].toBase58()); - + console.log(`${nftData.authorities[0].address} == ${nftAuthority[0].toBase58()}`); + if (nftData.authorities[0].address === nftAuthority[0].toBase58()) { nft = nftData; } @@ -115,7 +109,6 @@ const ChopTreeButton = () => { return; } try { - console.log("NFTid", nft.id, "NFT authority", nft.authorities[0].address); const transaction = await program.methods .chopTree(GAME_DATA_SEED, transactionCounter) @@ -126,20 +119,20 @@ const ChopTreeButton = () => { sessionToken: null, nftAuthority: nftAuthority[0].toBase58(), mint: nft.id, - tokenProgram: TOKEN_2022_PROGRAM_ID + tokenProgram: TOKEN_2022_PROGRAM_ID, }) - .transaction() + .transaction(); const txSig = await sendTransaction(transaction, connection, { skipPreflight: true, - }) - console.log(`https://explorer.solana.com/tx/${txSig}?cluster=devnet`) - } catch (error: any) { - console.log("error", `Chopping failed! ${error?.message}`) + }); + console.log(`https://explorer.solana.com/tx/${txSig}?cluster=devnet`); + } catch (error) { + console.log("error", `Chopping failed! ${error instanceof Error ? error.message : String(error)}`); } finally { - setIsLoadingMainWallet(false) + setIsLoadingMainWallet(false); } - }, [publicKey, playerDataPDA, connection, nftState]) + }, [publicKey, playerDataPDA, connection, nftState, transactionCounter, sendTransaction]); return ( <> @@ -148,26 +141,18 @@ const ChopTreeButton = () => { Energy Icon {sessionWallet && sessionWallet.sessionToken != null && ( - )} - )} - ) -} + ); +}; -export default ChopTreeButton +export default ChopTreeButton; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/DisplayGameState.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/DisplayGameState.tsx index f272d664e..86f60b377 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/DisplayGameState.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/DisplayGameState.tsx @@ -1,12 +1,12 @@ -import Image from "next/image" -import { HStack, VStack, Text } from "@chakra-ui/react" -import { useWallet } from "@solana/wallet-adapter-react" -import { useGameState } from "@/contexts/GameStateProvider" -import { TOTAL_WOOD_AVAILABLE } from "@/utils/anchor" +import { HStack, Text, VStack } from "@chakra-ui/react"; +import { useWallet } from "@solana/wallet-adapter-react"; +import Image from "next/image"; +import { useGameState } from "@/contexts/GameStateProvider"; +import { TOTAL_WOOD_AVAILABLE } from "@/utils/anchor"; const DisplayPlayerData = () => { - const { publicKey } = useWallet() - const { gameState, nextEnergyIn, totalWoodAvailable } = useGameState() + const { publicKey } = useWallet(); + const { gameState, nextEnergyIn, totalWoodAvailable } = useGameState(); return ( <> @@ -27,7 +27,7 @@ const DisplayPlayerData = () => { )} - ) -} + ); +}; -export default DisplayPlayerData +export default DisplayPlayerData; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/DisplayNfts.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/DisplayNfts.tsx index 01483c94e..986d338d5 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/DisplayNfts.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/DisplayNfts.tsx @@ -1,7 +1,7 @@ -import Image from "next/image" -import { useWallet } from "@solana/wallet-adapter-react" -import { useNftState } from "@/contexts/NftProvider" +import { useWallet } from "@solana/wallet-adapter-react"; +import Image from "next/image"; import { useState } from "react"; +import { useNftState } from "@/contexts/NftProvider"; export class Nft { name: string; @@ -14,26 +14,25 @@ export class Nft { } const DisplayNfts = () => { - const { publicKey } = useWallet() - const { nftState: nftState } = useNftState() + const { publicKey } = useWallet(); + const { nftState } = useNftState(); const [showItems, setShowItems] = useState(false); const handleButtonClick = () => { setShowItems(!showItems); }; - var myNfts = new Array(); + const myNfts: Nft[] = []; if (nftState != null) { - for (var i = 0; i < nftState.items.length; i++) { + for (let i = 0; i < nftState.items.length; i++) { try { - const nftData = nftState.items[i]; - let nft = new Nft(); - + const nft = new Nft(); + nft.name = nftData.content.metadata.name; nft.url = nftData.content.links.image; - + myNfts.push(nft); } catch (error) { console.log(error); @@ -42,14 +41,16 @@ const DisplayNfts = () => { } function onNftClickedCallback(nft: Nft): void { - window.alert("Nft clicked: " + nft.name); + window.alert(`Nft clicked: ${nft.name}`); } return ( <> {nftState && publicKey && (
- + {showItems && (
{myNfts.map((nft) => ( @@ -67,7 +68,6 @@ const DisplayNfts = () => { ) : (
Error loading image
)} -
))} @@ -77,6 +77,6 @@ const DisplayNfts = () => { )} ); -} +}; -export default DisplayNfts +export default DisplayNfts; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/InitPlayerButton.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/InitPlayerButton.tsx index 091308e54..47d2a1cc1 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/InitPlayerButton.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/InitPlayerButton.tsx @@ -1,21 +1,21 @@ -import { useCallback, useState } from "react" -import { Button } from "@chakra-ui/react" -import { SystemProgram } from "@solana/web3.js" -import { useConnection, useWallet } from "@solana/wallet-adapter-react" -import { useGameState } from "@/contexts/GameStateProvider" -import { GAME_DATA_SEED, gameDataPDA, program } from "@/utils/anchor" +import { Button } from "@chakra-ui/react"; +import { useConnection, useWallet } from "@solana/wallet-adapter-react"; +import { SystemProgram } from "@solana/web3.js"; +import { useCallback, useState } from "react"; +import { useGameState } from "@/contexts/GameStateProvider"; +import { GAME_DATA_SEED, gameDataPDA, program } from "@/utils/anchor"; const InitPlayerButton = () => { - const { publicKey, sendTransaction } = useWallet() - const { connection } = useConnection() - const [isLoading, setIsLoading] = useState(false) - const { gameState, playerDataPDA } = useGameState() + const { publicKey, sendTransaction } = useWallet(); + const { connection } = useConnection(); + const [isLoading, setIsLoading] = useState(false); + const { gameState, playerDataPDA } = useGameState(); // Init player button click handler const handleClick = useCallback(async () => { - if (!publicKey || !playerDataPDA) return + if (!publicKey || !playerDataPDA) return; - setIsLoading(true) + setIsLoading(true); try { const transaction = await program.methods @@ -26,19 +26,19 @@ const InitPlayerButton = () => { signer: publicKey, systemProgram: SystemProgram.programId, }) - .transaction() + .transaction(); const txSig = await sendTransaction(transaction, connection, { skipPreflight: true, - }) + }); - console.log(`https://explorer.solana.com/tx/${txSig}?cluster=devnet`) + console.log(`https://explorer.solana.com/tx/${txSig}?cluster=devnet`); } catch (error) { - console.log(error) + console.log(error); } finally { - setIsLoading(false) // set loading state back to false + setIsLoading(false); // set loading state back to false } - }, [publicKey, playerDataPDA, connection]) + }, [publicKey, playerDataPDA, connection, sendTransaction]); return ( <> @@ -48,7 +48,7 @@ const InitPlayerButton = () => { )} - ) -} + ); +}; -export default InitPlayerButton +export default InitPlayerButton; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/MintNftButton.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/MintNftButton.tsx index 2590c697b..48115b136 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/MintNftButton.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/MintNftButton.tsx @@ -1,30 +1,26 @@ -import Image from "next/image" -import { useCallback, useState } from "react" -import { Button, HStack, VStack } from "@chakra-ui/react" -import { useConnection, useWallet } from "@solana/wallet-adapter-react" -import { useGameState } from "@/contexts/GameStateProvider" -import { program } from "@/utils/anchor" -import { Keypair, PublicKey, SystemProgram } from "@solana/web3.js" -import { web3 } from "@coral-xyz/anchor" -import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, getAssociatedTokenAddressSync } from "@solana/spl-token"; +import { Button, HStack, VStack } from "@chakra-ui/react"; +import { web3 } from "@coral-xyz/anchor"; +import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import { useConnection, useWallet } from "@solana/wallet-adapter-react"; +import { Keypair, PublicKey, SystemProgram } from "@solana/web3.js"; +import Image from "next/image"; +import { useCallback, useState } from "react"; +import { useGameState } from "@/contexts/GameStateProvider"; +import { program } from "@/utils/anchor"; const MintNftButton = () => { - const { publicKey, sendTransaction, wallet } = useWallet() - const { connection } = useConnection() - const { gameState, playerDataPDA } = useGameState() - const [isLoadingMainWallet, showSpinner] = useState(false) + const { publicKey, sendTransaction } = useWallet(); + const { connection } = useConnection(); + const { gameState, playerDataPDA } = useGameState(); + const [isLoadingMainWallet, showSpinner] = useState(false); const onMintNftClick = useCallback(async () => { - if (!publicKey || !playerDataPDA) return + if (!publicKey || !playerDataPDA) return; - showSpinner(true) + showSpinner(true); try { - - const nftAuthority = await PublicKey.findProgramAddress( - [Buffer.from("nft_authority")], - program.programId - ); + const nftAuthority = await PublicKey.findProgramAddress([Buffer.from("nft_authority")], program.programId); const mint = new Keypair(); @@ -52,19 +48,18 @@ const MintNftButton = () => { console.log("transaction", transaction); - const txSig = await sendTransaction(transaction, connection,{ + const txSig = await sendTransaction(transaction, connection, { signers: [mint], - skipPreflight: true - } ); + skipPreflight: true, + }); - console.log(`https://explorer.solana.com/tx/${txSig}?cluster=devnet`) - - } catch (error: any) { - console.log("error", `Minting failed! ${error?.message} ${error?.stack}`) + console.log(`https://explorer.solana.com/tx/${txSig}?cluster=devnet`); + } catch (error) { + console.log("error", `Minting failed! ${error instanceof Error ? error.message : String(error)}`); } finally { - showSpinner(false) + showSpinner(false); } - }, [publicKey, playerDataPDA, connection]) + }, [publicKey, playerDataPDA, connection, sendTransaction]); return ( <> @@ -72,18 +67,14 @@ const MintNftButton = () => { Energy Icon - )} - ) -} + ); +}; -export default MintNftButton +export default MintNftButton; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/RequestAirdrop.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/RequestAirdrop.tsx index a6f8e77cc..da9b89e68 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/RequestAirdrop.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/RequestAirdrop.tsx @@ -1,37 +1,37 @@ -import { useCallback, useEffect, useState } from "react" -import { Button, Text } from "@chakra-ui/react" -import { LAMPORTS_PER_SOL } from "@solana/web3.js" -import { useConnection, useWallet } from "@solana/wallet-adapter-react" +import { Button, Text } from "@chakra-ui/react"; +import { useConnection, useWallet } from "@solana/wallet-adapter-react"; +import { LAMPORTS_PER_SOL } from "@solana/web3.js"; +import { useCallback, useEffect, useState } from "react"; const RequestAirdrop = () => { - const { publicKey } = useWallet() - const { connection } = useConnection() - const [balance, setBalance] = useState(0) - const [isLoading, setIsLoading] = useState(false) + const { publicKey } = useWallet(); + const { connection } = useConnection(); + const [balance, setBalance] = useState(0); + const [isLoading, setIsLoading] = useState(false); const getBalance = useCallback(async () => { - if (!publicKey) return - const balance = await connection.getBalance(publicKey, "confirmed") - setBalance(balance / LAMPORTS_PER_SOL) - }, [publicKey, connection]) + if (!publicKey) return; + const balance = await connection.getBalance(publicKey, "confirmed"); + setBalance(balance / LAMPORTS_PER_SOL); + }, [publicKey, connection]); const onClick = useCallback(async () => { - setIsLoading(true) - if (!publicKey) return + setIsLoading(true); + if (!publicKey) return; try { - const txSig = await connection.requestAirdrop(publicKey, LAMPORTS_PER_SOL) - await connection.confirmTransaction(txSig) - getBalance() - } catch (error: any) { - alert(error.message) + const txSig = await connection.requestAirdrop(publicKey, LAMPORTS_PER_SOL); + await connection.confirmTransaction(txSig); + getBalance(); + } catch (error) { + alert(error instanceof Error ? error.message : String(error)); } finally { - setIsLoading(false) + setIsLoading(false); } - }, [publicKey, connection, getBalance]) + }, [publicKey, connection, getBalance]); useEffect(() => { - getBalance() - }, [getBalance]) + getBalance(); + }, [getBalance]); return ( <> @@ -44,7 +44,7 @@ const RequestAirdrop = () => { Balance: {Number(balance).toFixed(3)} ))} - ) -} + ); +}; -export default RequestAirdrop +export default RequestAirdrop; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/SessionKeyButton.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/SessionKeyButton.tsx index 7567e9efb..e3036c776 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/SessionKeyButton.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/SessionKeyButton.tsx @@ -1,65 +1,55 @@ -import { useState } from "react" -import { Button } from "@chakra-ui/react" -import { useWallet } from "@solana/wallet-adapter-react" -import { useSessionWallet } from "@magicblock-labs/gum-react-sdk" -import { useGameState } from "@/contexts/GameStateProvider" -import { program } from "@/utils/anchor" +import { Button } from "@chakra-ui/react"; +import { useSessionWallet } from "@magicblock-labs/gum-react-sdk"; +import { useWallet } from "@solana/wallet-adapter-react"; +import { useState } from "react"; +import { useGameState } from "@/contexts/GameStateProvider"; +import { program } from "@/utils/anchor"; const SessionKeyButton = () => { - const { publicKey } = useWallet() - const { gameState } = useGameState() - const sessionWallet = useSessionWallet() - const [isLoading, setIsLoading] = useState(false) + const { publicKey } = useWallet(); + const { gameState } = useGameState(); + const sessionWallet = useSessionWallet(); + const [isLoading, setIsLoading] = useState(false); const handleCreateSession = async () => { - setIsLoading(true) - const topUp = true - const expiryInMinutes = 600 + setIsLoading(true); + const topUp = true; + const expiryInMinutes = 600; try { - const session = await sessionWallet.createSession( - program.programId, - topUp, - expiryInMinutes - ) - console.log("Session created:", session) + const session = await sessionWallet.createSession(program.programId, topUp, expiryInMinutes); + console.log("Session created:", session); } catch (error) { - console.error("Failed to create session:", error) + console.error("Failed to create session:", error); } finally { - setIsLoading(false) + setIsLoading(false); } - } + }; const handleRevokeSession = async () => { - setIsLoading(true) + setIsLoading(true); try { - await sessionWallet.revokeSession() - console.log("Session revoked") + await sessionWallet.revokeSession(); + console.log("Session revoked"); } catch (error) { - console.error("Failed to revoke session:", error) + console.error("Failed to revoke session:", error); } finally { - setIsLoading(false) + setIsLoading(false); } - } + }; return ( <> {publicKey && gameState && ( )} - ) -} + ); +}; -export default SessionKeyButton +export default SessionKeyButton; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/WalletMultiButton.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/WalletMultiButton.tsx index 8f2380015..d3cfefe14 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/WalletMultiButton.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/components/WalletMultiButton.tsx @@ -1,13 +1,12 @@ -import dynamic from "next/dynamic" +import dynamic from "next/dynamic"; export const WalletMultiButtonDynamic = dynamic( - async () => - (await import("@solana/wallet-adapter-react-ui")).WalletMultiButton, - { ssr: false } -) + async () => (await import("@solana/wallet-adapter-react-ui")).WalletMultiButton, + { ssr: false }, +); const WalletMultiButton = () => { - return -} + return ; +}; -export default WalletMultiButton +export default WalletMultiButton; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/GameStateProvider.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/GameStateProvider.tsx index 4e9127870..182a752af 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/GameStateProvider.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/GameStateProvider.tsx @@ -1,128 +1,116 @@ -import { createContext, useContext, useEffect, useState } from "react" -import { PublicKey } from "@solana/web3.js" -import { useConnection, useWallet } from "@solana/wallet-adapter-react" +import { BN } from "@coral-xyz/anchor"; +import { useConnection, useWallet } from "@solana/wallet-adapter-react"; +import { PublicKey } from "@solana/web3.js"; +import { createContext, useContext, useEffect, useState } from "react"; import { - program, - PlayerData, + GAME_DATA_SEED, + type GameData, MAX_ENERGY, + type PlayerData, + program, TIME_TO_REFILL_ENERGY, - GameData, - GAME_DATA_SEED, -} from "@/utils/anchor" -import { BN } from "@coral-xyz/anchor" +} from "@/utils/anchor"; const GameStateContext = createContext<{ - playerDataPDA: PublicKey | null - gameState: PlayerData | null - nextEnergyIn: number - totalWoodAvailable: number | null + playerDataPDA: PublicKey | null; + gameState: PlayerData | null; + nextEnergyIn: number; + totalWoodAvailable: number | null; }>({ playerDataPDA: null, gameState: null, nextEnergyIn: 0, - totalWoodAvailable: 0 -}) - -export const useGameState = () => useContext(GameStateContext) - -export const GameStateProvider = ({ - children, -}: { - children: React.ReactNode -}) => { - const { publicKey } = useWallet() - const { connection } = useConnection() - - const [playerDataPDA, setPlayerData] = useState(null) - const [playerState, setPlayerState] = useState(null) - const [timePassed, setTimePassed] = useState([]) - const [nextEnergyIn, setEnergyNextIn] = useState(0) - const [gameDataPDA, setGameDataPDA] = useState(null) - const [gameData, setGameData] = useState(null) - const [totalWoodAvailable, setTotalWoodAvailable] = useState(0) + totalWoodAvailable: 0, +}); + +export const useGameState = () => useContext(GameStateContext); + +export const GameStateProvider = ({ children }: { children: React.ReactNode }) => { + const { publicKey } = useWallet(); + const { connection } = useConnection(); + + const [playerDataPDA, setPlayerData] = useState(null); + const [playerState, setPlayerState] = useState(null); + const [_timePassed, setTimePassed] = useState(0); + const [nextEnergyIn, setEnergyNextIn] = useState(0); + const [gameDataPDA, setGameDataPDA] = useState(null); + const [_gameData, setGameData] = useState(null); + const [totalWoodAvailable, setTotalWoodAvailable] = useState(0); useEffect(() => { - setPlayerState(null) + setPlayerState(null); if (!publicKey) { - return + return; } const [pda] = PublicKey.findProgramAddressSync( [Buffer.from("player", "utf8"), publicKey.toBuffer()], - program.programId - ) - setPlayerData(pda) + program.programId, + ); + setPlayerData(pda); program.account.playerData .fetch(pda) .then((data) => { - setPlayerState(data) - }) - .catch((error) => { - window.alert("No player data found, please init!") + setPlayerState(data); }) + .catch((_error) => { + window.alert("No player data found, please init!"); + }); connection.onAccountChange(pda, (account) => { - setPlayerState(program.coder.accounts.decode("playerData", account.data)) - }) - }, [publicKey]) + setPlayerState(program.coder.accounts.decode("playerData", account.data)); + }); + }, [publicKey, connection.onAccountChange]); useEffect(() => { - setGameData(null) + setGameData(null); if (!publicKey) { - return + return; } - const [pda] = PublicKey.findProgramAddressSync( - [Buffer.from(GAME_DATA_SEED, "utf8")], - program.programId - ) - setGameDataPDA(gameDataPDA) + const [pda] = PublicKey.findProgramAddressSync([Buffer.from(GAME_DATA_SEED, "utf8")], program.programId); + setGameDataPDA(gameDataPDA); program.account.gameData .fetch(pda) .then((data) => { - setGameData(data) + setGameData(data); setTotalWoodAvailable(data.totalWoodCollected.toNumber()); }) - .catch((error) => { - window.alert("No game data found, please init!") - }) + .catch((_error) => { + window.alert("No game data found, please init!"); + }); connection.onAccountChange(pda, (account) => { - const newGameData = program.coder.accounts.decode("gameData", account.data) + const newGameData = program.coder.accounts.decode("gameData", account.data); setGameData(newGameData); setTotalWoodAvailable(newGameData.totalWoodCollected.toNumber()); - }) - }, [publicKey]) - + }); + }, [publicKey, connection.onAccountChange, gameDataPDA]); useEffect(() => { const interval = setInterval(async () => { - if ( - playerState == null || - playerState.lastLogin == undefined || - playerState.energy.toNumber() >= MAX_ENERGY - ) { + if (playerState == null || playerState.lastLogin === undefined || playerState.energy.toNumber() >= MAX_ENERGY) { return; } - + const lastLoginTime = playerState.lastLogin.toNumber() * 1000; const currentTime = Date.now(); let timePassed = (currentTime - lastLoginTime) / 1000; - + while (timePassed >= TIME_TO_REFILL_ENERGY.toNumber() && playerState.energy.toNumber() < MAX_ENERGY) { playerState.energy = playerState.energy.add(new BN(1)); playerState.lastLogin = playerState.lastLogin.add(TIME_TO_REFILL_ENERGY); timePassed -= TIME_TO_REFILL_ENERGY.toNumber(); } - + setTimePassed(timePassed); - + const nextEnergyIn = Math.floor(TIME_TO_REFILL_ENERGY.toNumber() - timePassed); setEnergyNextIn(nextEnergyIn > 0 ? nextEnergyIn : 0); }, 1000); - return () => clearInterval(interval) - }, [playerState, timePassed, nextEnergyIn]) + return () => clearInterval(interval); + }, [playerState]); return ( {children} - ) -} + ); +}; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/NftProvider.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/NftProvider.tsx index 8f115f789..376cdc018 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/NftProvider.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/NftProvider.tsx @@ -1,38 +1,35 @@ -import { createContext, useContext, useEffect, useState } from "react" -import { PublicKey } from "@solana/web3.js" -import { useWallet } from "@solana/wallet-adapter-react" -import { - CONNECTION, -} from "@/utils/anchor" +import { useWallet } from "@solana/wallet-adapter-react"; +import type { PublicKey } from "@solana/web3.js"; +import { createContext, useCallback, useContext, useEffect, useState } from "react"; +import { CONNECTION } from "@/utils/anchor"; + +interface DasNftItem { + id: string; + authorities: Array<{ address: string } | string>; + content: { + metadata: { name: string }; + links: { image: string }; + }; +} + +interface DasNftState { + items: DasNftItem[]; +} const NftContext = createContext<{ - nftState: any | null + nftState: DasNftState | null; }>({ nftState: null, -}) +}); -export const useNftState = () => useContext(NftContext) +export const useNftState = () => useContext(NftContext); -export const NftProvider = ({ - children, -}: { - children: React.ReactNode -}) => { - const { publicKey } = useWallet() +export const NftProvider = ({ children }: { children: React.ReactNode }) => { + const { publicKey } = useWallet(); - const [nftState, setNftState] = useState(null) - - useEffect( () => { - setNftState(null) - if (!publicKey) { - return - } - - getAssetsByOwner(publicKey); + const [nftState, setNftState] = useState(null); - }, [publicKey]); - - async function getAssetsByOwner(ownerAddress: PublicKey) { + const getAssetsByOwner = useCallback(async (ownerAddress: PublicKey) => { const sortBy = { sortBy: "created", sortDirection: "asc", @@ -47,12 +44,21 @@ export const NftProvider = ({ limit, page, before, - after + after, ); - setNftState(allAssetsOwned); + setNftState(allAssetsOwned as DasNftState); console.log(allAssetsOwned); - } + }, []); + + useEffect(() => { + setNftState(null); + if (!publicKey) { + return; + } + + getAssetsByOwner(publicKey); + }, [publicKey, getAssetsByOwner]); return ( {children} - ) -} + ); +}; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/SessionProvider.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/SessionProvider.tsx index 619d442d5..57d8a2baf 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/SessionProvider.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/SessionProvider.tsx @@ -1,26 +1,18 @@ -import { SessionWalletProvider, useSessionKeyManager } from "@magicblock-labs/gum-react-sdk" +import { SessionWalletProvider, useSessionKeyManager } from "@magicblock-labs/gum-react-sdk"; -import { - AnchorWallet, - useAnchorWallet, - useConnection, -} from "@solana/wallet-adapter-react" +import { type AnchorWallet, useAnchorWallet, useConnection } from "@solana/wallet-adapter-react"; interface SessionProviderProps { - children: React.ReactNode + children: React.ReactNode; } const SessionProvider: React.FC = ({ children }) => { - const { connection } = useConnection() - const anchorWallet = useAnchorWallet() as AnchorWallet - const cluster = "devnet" // or "mainnet-beta", "testnet", "localnet" - const sessionWallet = useSessionKeyManager(anchorWallet, connection, cluster) + const { connection } = useConnection(); + const anchorWallet = useAnchorWallet() as AnchorWallet; + const cluster = "devnet"; // or "mainnet-beta", "testnet", "localnet" + const sessionWallet = useSessionKeyManager(anchorWallet, connection, cluster); - return ( - - {children} - - ) -} + return {children}; +}; -export default SessionProvider +export default SessionProvider; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/WalletContextProvider.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/WalletContextProvider.tsx index 97a625de2..1b3e9cdc7 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/WalletContextProvider.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/contexts/WalletContextProvider.tsx @@ -1,28 +1,17 @@ -import { FC, ReactNode, useMemo } from "react" -import { WalletAdapterNetwork } from "@solana/wallet-adapter-base" -import { - ConnectionProvider, - WalletProvider, -} from "@solana/wallet-adapter-react" -import { WalletModalProvider } from "@solana/wallet-adapter-react-ui" -import { - PhantomWalletAdapter, - SolflareWalletAdapter, -} from "@solana/wallet-adapter-wallets" -import { clusterApiUrl } from "@solana/web3.js" -require("@solana/wallet-adapter-react-ui/styles.css") +import { WalletAdapterNetwork } from "@solana/wallet-adapter-base"; +import { ConnectionProvider, WalletProvider } from "@solana/wallet-adapter-react"; +import { WalletModalProvider } from "@solana/wallet-adapter-react-ui"; +import { PhantomWalletAdapter, SolflareWalletAdapter } from "@solana/wallet-adapter-wallets"; +import { clusterApiUrl } from "@solana/web3.js"; +import { type FC, type ReactNode, useMemo } from "react"; + +require("@solana/wallet-adapter-react-ui/styles.css"); const WalletContextProvider: FC<{ children: ReactNode }> = ({ children }) => { - const network = WalletAdapterNetwork.Devnet - const endpoint = useMemo(() => clusterApiUrl(network), [network]) + const network = WalletAdapterNetwork.Devnet; + const endpoint = useMemo(() => clusterApiUrl(network), []); - const wallets = useMemo( - () => [ - new PhantomWalletAdapter(), - new SolflareWalletAdapter(), - ], - [network] - ) + const wallets = useMemo(() => [new PhantomWalletAdapter(), new SolflareWalletAdapter()], []); return ( @@ -30,7 +19,7 @@ const WalletContextProvider: FC<{ children: ReactNode }> = ({ children }) => { {children} - ) -} + ); +}; -export default WalletContextProvider +export default WalletContextProvider; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/idl/extension_nft.ts b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/idl/extension_nft.ts index b77acef1c..f31836532 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/idl/extension_nft.ts +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/idl/extension_nft.ts @@ -1,134 +1,134 @@ export type ExtensionNft = { - version: '0.1.0'; - name: 'extension_nft'; + version: "0.1.0"; + name: "extension_nft"; instructions: [ { - name: 'initPlayer'; + name: "initPlayer"; accounts: [ { - name: 'player'; + name: "player"; isMut: true; isSigner: false; }, { - name: 'gameData'; + name: "gameData"; isMut: true; isSigner: false; }, { - name: 'signer'; + name: "signer"; isMut: true; isSigner: true; }, { - name: 'systemProgram'; + name: "systemProgram"; isMut: false; isSigner: false; }, ]; args: [ { - name: 'levelSeed'; - type: 'string'; + name: "levelSeed"; + type: "string"; }, ]; }, { - name: 'chopTree'; + name: "chopTree"; accounts: [ { - name: 'sessionToken'; + name: "sessionToken"; isMut: false; isSigner: false; isOptional: true; }, { - name: 'player'; + name: "player"; isMut: true; isSigner: false; }, { - name: 'gameData'; + name: "gameData"; isMut: true; isSigner: false; }, { - name: 'signer'; + name: "signer"; isMut: true; isSigner: true; }, { - name: 'systemProgram'; + name: "systemProgram"; isMut: false; isSigner: false; }, { - name: 'mint'; + name: "mint"; isMut: true; isSigner: false; }, { - name: 'nftAuthority'; + name: "nftAuthority"; isMut: true; isSigner: false; }, { - name: 'tokenProgram'; + name: "tokenProgram"; isMut: false; isSigner: false; }, ]; args: [ { - name: 'levelSeed'; - type: 'string'; + name: "levelSeed"; + type: "string"; }, { - name: 'counter'; - type: 'u16'; + name: "counter"; + type: "u16"; }, ]; }, { - name: 'mintNft'; + name: "mintNft"; accounts: [ { - name: 'signer'; + name: "signer"; isMut: true; isSigner: true; }, { - name: 'systemProgram'; + name: "systemProgram"; isMut: false; isSigner: false; }, { - name: 'tokenProgram'; + name: "tokenProgram"; isMut: false; isSigner: false; }, { - name: 'tokenAccount'; + name: "tokenAccount"; isMut: true; isSigner: false; }, { - name: 'mint'; + name: "mint"; isMut: true; isSigner: true; }, { - name: 'rent'; + name: "rent"; isMut: false; isSigner: false; }, { - name: 'associatedTokenProgram'; + name: "associatedTokenProgram"; isMut: false; isSigner: false; }, { - name: 'nftAuthority'; + name: "nftAuthority"; isMut: true; isSigner: false; }, @@ -138,60 +138,60 @@ export type ExtensionNft = { ]; accounts: [ { - name: 'nftAuthority'; + name: "nftAuthority"; type: { - kind: 'struct'; + kind: "struct"; fields: []; }; }, { - name: 'gameData'; + name: "gameData"; type: { - kind: 'struct'; + kind: "struct"; fields: [ { - name: 'totalWoodCollected'; - type: 'u64'; + name: "totalWoodCollected"; + type: "u64"; }, ]; }; }, { - name: 'playerData'; + name: "playerData"; type: { - kind: 'struct'; + kind: "struct"; fields: [ { - name: 'authority'; - type: 'publicKey'; + name: "authority"; + type: "publicKey"; }, { - name: 'name'; - type: 'string'; + name: "name"; + type: "string"; }, { - name: 'level'; - type: 'u8'; + name: "level"; + type: "u8"; }, { - name: 'xp'; - type: 'u64'; + name: "xp"; + type: "u64"; }, { - name: 'wood'; - type: 'u64'; + name: "wood"; + type: "u64"; }, { - name: 'energy'; - type: 'u64'; + name: "energy"; + type: "u64"; }, { - name: 'lastLogin'; - type: 'i64'; + name: "lastLogin"; + type: "i64"; }, { - name: 'lastId'; - type: 'u16'; + name: "lastId"; + type: "u16"; }, ]; }; @@ -200,148 +200,148 @@ export type ExtensionNft = { errors: [ { code: 6000; - name: 'NotEnoughEnergy'; - msg: 'Not enough energy'; + name: "NotEnoughEnergy"; + msg: "Not enough energy"; }, { code: 6001; - name: 'WrongAuthority'; - msg: 'Wrong Authority'; + name: "WrongAuthority"; + msg: "Wrong Authority"; }, ]; }; export const IDL: ExtensionNft = { - version: '0.1.0', - name: 'extension_nft', + version: "0.1.0", + name: "extension_nft", instructions: [ { - name: 'initPlayer', + name: "initPlayer", accounts: [ { - name: 'player', + name: "player", isMut: true, isSigner: false, }, { - name: 'gameData', + name: "gameData", isMut: true, isSigner: false, }, { - name: 'signer', + name: "signer", isMut: true, isSigner: true, }, { - name: 'systemProgram', + name: "systemProgram", isMut: false, isSigner: false, }, ], args: [ { - name: 'levelSeed', - type: 'string', + name: "levelSeed", + type: "string", }, ], }, { - name: 'chopTree', + name: "chopTree", accounts: [ { - name: 'sessionToken', + name: "sessionToken", isMut: false, isSigner: false, isOptional: true, }, { - name: 'player', + name: "player", isMut: true, isSigner: false, }, { - name: 'gameData', + name: "gameData", isMut: true, isSigner: false, }, { - name: 'signer', + name: "signer", isMut: true, isSigner: true, }, { - name: 'systemProgram', + name: "systemProgram", isMut: false, isSigner: false, }, { - name: 'mint', + name: "mint", isMut: true, isSigner: false, }, { - name: 'nftAuthority', + name: "nftAuthority", isMut: true, isSigner: false, }, { - name: 'tokenProgram', + name: "tokenProgram", isMut: false, isSigner: false, }, ], args: [ { - name: 'levelSeed', - type: 'string', + name: "levelSeed", + type: "string", }, { - name: 'counter', - type: 'u16', + name: "counter", + type: "u16", }, ], }, { - name: 'mintNft', + name: "mintNft", accounts: [ { - name: 'signer', + name: "signer", isMut: true, isSigner: true, }, { - name: 'systemProgram', + name: "systemProgram", isMut: false, isSigner: false, }, { - name: 'tokenProgram', + name: "tokenProgram", isMut: false, isSigner: false, }, { - name: 'tokenAccount', + name: "tokenAccount", isMut: true, isSigner: false, }, { - name: 'mint', + name: "mint", isMut: true, isSigner: true, }, { - name: 'rent', + name: "rent", isMut: false, isSigner: false, }, { - name: 'associatedTokenProgram', + name: "associatedTokenProgram", isMut: false, isSigner: false, }, { - name: 'nftAuthority', + name: "nftAuthority", isMut: true, isSigner: false, }, @@ -351,60 +351,60 @@ export const IDL: ExtensionNft = { ], accounts: [ { - name: 'nftAuthority', + name: "nftAuthority", type: { - kind: 'struct', + kind: "struct", fields: [], }, }, { - name: 'gameData', + name: "gameData", type: { - kind: 'struct', + kind: "struct", fields: [ { - name: 'totalWoodCollected', - type: 'u64', + name: "totalWoodCollected", + type: "u64", }, ], }, }, { - name: 'playerData', + name: "playerData", type: { - kind: 'struct', + kind: "struct", fields: [ { - name: 'authority', - type: 'publicKey', + name: "authority", + type: "publicKey", }, { - name: 'name', - type: 'string', + name: "name", + type: "string", }, { - name: 'level', - type: 'u8', + name: "level", + type: "u8", }, { - name: 'xp', - type: 'u64', + name: "xp", + type: "u64", }, { - name: 'wood', - type: 'u64', + name: "wood", + type: "u64", }, { - name: 'energy', - type: 'u64', + name: "energy", + type: "u64", }, { - name: 'lastLogin', - type: 'i64', + name: "lastLogin", + type: "i64", }, { - name: 'lastId', - type: 'u16', + name: "lastId", + type: "u16", }, ], }, @@ -413,13 +413,13 @@ export const IDL: ExtensionNft = { errors: [ { code: 6000, - name: 'NotEnoughEnergy', - msg: 'Not enough energy', + name: "NotEnoughEnergy", + msg: "Not enough energy", }, { code: 6001, - name: 'WrongAuthority', - msg: 'Wrong Authority', + name: "WrongAuthority", + msg: "Wrong Authority", }, ], }; diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/next.config.js b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/next.config.js index f4fad9bea..9d6954c83 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/next.config.js +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/next.config.js @@ -6,8 +6,8 @@ const nextConfig = { images: { remotePatterns: [ { - protocol: 'https', - hostname: '**', + protocol: "https", + hostname: "**", }, ], }, diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/package.json b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/package.json index befffb0a7..bccff5cb3 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/package.json +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/package.json @@ -11,7 +11,7 @@ "dependencies": { "@chakra-ui/next-js": "^2.1.3", "@chakra-ui/react": "^2.6.1", - "@anchor-lang/core": "1.0.0-rc.5", + "@anchor-lang/core": "1.0.0", "@coral-xyz/spl-token": "0.30.0", "@emotion/react": "^11.11.0", "@emotion/styled": "^11.11.0", diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/_app.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/_app.tsx index fd00cdf93..7bb118b2b 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/_app.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/_app.tsx @@ -1,22 +1,22 @@ -import { ChakraProvider } from "@chakra-ui/react" -import WalletContextProvider from "../contexts/WalletContextProvider" -import SessionProvider from "@/contexts/SessionProvider" -import { GameStateProvider } from "@/contexts/GameStateProvider" -import type { AppProps } from "next/app" -import { NftProvider } from "@/contexts/NftProvider" +import { ChakraProvider } from "@chakra-ui/react"; +import type { AppProps } from "next/app"; +import { GameStateProvider } from "@/contexts/GameStateProvider"; +import { NftProvider } from "@/contexts/NftProvider"; +import SessionProvider from "@/contexts/SessionProvider"; +import WalletContextProvider from "../contexts/WalletContextProvider"; export default function App({ Component, pageProps }: AppProps) { return ( - - - - + + + + - ) + ); } diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/_document.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/_document.tsx index 54e8bf3e2..ffc3f3ccc 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/_document.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/_document.tsx @@ -1,4 +1,4 @@ -import { Html, Head, Main, NextScript } from 'next/document' +import { Head, Html, Main, NextScript } from "next/document"; export default function Document() { return ( @@ -9,5 +9,5 @@ export default function Document() { - ) + ); } diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/api/hello.ts b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/api/hello.ts index 32a1340fe..e1b0dd0d2 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/api/hello.ts +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/api/hello.ts @@ -1,10 +1,10 @@ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from 'next'; +import type { NextApiRequest, NextApiResponse } from "next"; type Data = { name: string; }; export default function handler(_req: NextApiRequest, res: NextApiResponse) { - res.status(200).json({ name: 'John Doe' }); + res.status(200).json({ name: "John Doe" }); } diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/index.tsx b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/index.tsx index a578072d2..865c00100 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/index.tsx +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/pages/index.tsx @@ -1,16 +1,16 @@ -import { Box, Flex, Heading, Spacer, VStack, Text } from "@chakra-ui/react" -import { useWallet } from "@solana/wallet-adapter-react" -import WalletMultiButton from "@/components/WalletMultiButton" -import DisplayGameState from "@/components/DisplayGameState" -import InitPlayerButton from "@/components/InitPlayerButton" -import SessionKeyButton from "@/components/SessionKeyButton" -import ChopTreeButton from "@/components/ChopTreeButton" -import RequestAirdrop from "@/components/RequestAirdrop" -import DisplayNfts from "@/components/DisplayNfts" -import MintNftButton from "@/components/MintNftButton" +import { Box, Flex, Heading, Spacer, Text, VStack } from "@chakra-ui/react"; +import { useWallet } from "@solana/wallet-adapter-react"; +import ChopTreeButton from "@/components/ChopTreeButton"; +import DisplayGameState from "@/components/DisplayGameState"; +import DisplayNfts from "@/components/DisplayNfts"; +import InitPlayerButton from "@/components/InitPlayerButton"; +import MintNftButton from "@/components/MintNftButton"; +import RequestAirdrop from "@/components/RequestAirdrop"; +import SessionKeyButton from "@/components/SessionKeyButton"; +import WalletMultiButton from "@/components/WalletMultiButton"; export default function Home() { - const { publicKey } = useWallet() + const { publicKey } = useWallet(); return ( @@ -30,5 +30,5 @@ export default function Home() { - ) + ); } diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/styles/Home.module.css b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/styles/Home.module.css index 9411a5e6f..25760859a 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/styles/Home.module.css +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/styles/Home.module.css @@ -51,7 +51,9 @@ border-radius: var(--border-radius); background: rgba(var(--card-rgb), 0); border: 1px solid rgba(var(--card-border-rgb), 0); - transition: background 200ms, border 200ms; + transition: + background 200ms, + border 200ms; } .card span { @@ -97,7 +99,7 @@ .center::before, .center::after { - content: ''; + content: ""; left: 50%; position: absolute; filter: blur(45px); @@ -178,11 +180,7 @@ border-radius: 0; border: none; border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); - background: linear-gradient( - to bottom, - rgba(var(--background-start-rgb), 1), - rgba(var(--callout-rgb), 0.5) - ); + background: linear-gradient(to bottom, rgba(var(--background-start-rgb), 1), rgba(var(--callout-rgb), 0.5)); background-clip: padding-box; backdrop-filter: blur(24px); } @@ -193,11 +191,7 @@ inset: auto 0 0; padding: 2rem; height: 200px; - background: linear-gradient( - to bottom, - transparent 0%, - rgb(var(--background-end-rgb)) 40% - ); + background: linear-gradient(to bottom, transparent 0%, rgb(var(--background-end-rgb)) 40%); z-index: 1; } } diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/styles/globals.css b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/styles/globals.css index d4f491e15..bcc3a6c25 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/styles/globals.css +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/styles/globals.css @@ -1,9 +1,10 @@ :root { --max-width: 1100px; --border-radius: 12px; - --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono', - 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', - 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace; + --font-mono: + ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", + "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", + "Fira Mono", "Droid Sans Mono", "Courier New", monospace; --foreground-rgb: 0, 0, 0; --background-start-rgb: 214, 219, 220; @@ -17,22 +18,11 @@ #0071ff33 160deg, transparent 360deg ); - --secondary-glow: radial-gradient( - rgba(255, 255, 255, 1), - rgba(255, 255, 255, 0) - ); + --secondary-glow: radial-gradient(rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); --tile-start-rgb: 239, 245, 249; --tile-end-rgb: 228, 232, 233; - --tile-border: conic-gradient( - #00000080, - #00000040, - #00000030, - #00000020, - #00000010, - #00000010, - #00000080 - ); + --tile-border: conic-gradient(#00000080, #00000040, #00000030, #00000020, #00000010, #00000010, #00000080); --callout-rgb: 238, 240, 241; --callout-border-rgb: 172, 175, 176; @@ -47,24 +37,11 @@ --background-end-rgb: 0, 0, 0; --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); - --secondary-glow: linear-gradient( - to bottom right, - rgba(1, 65, 255, 0), - rgba(1, 65, 255, 0), - rgba(1, 65, 255, 0.3) - ); + --secondary-glow: linear-gradient(to bottom right, rgba(1, 65, 255, 0), rgba(1, 65, 255, 0), rgba(1, 65, 255, 0.3)); --tile-start-rgb: 2, 13, 46; --tile-end-rgb: 2, 5, 19; - --tile-border: conic-gradient( - #ffffff80, - #ffffff40, - #ffffff30, - #ffffff20, - #ffffff10, - #ffffff10, - #ffffff80 - ); + --tile-border: conic-gradient(#ffffff80, #ffffff40, #ffffff30, #ffffff20, #ffffff10, #ffffff10, #ffffff80); --callout-rgb: 20, 20, 20; --callout-border-rgb: 108, 108, 108; @@ -87,12 +64,7 @@ body { body { color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); + background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb)); } a { diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/utils/anchor.ts b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/utils/anchor.ts index fe83416f4..8db5bcd23 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/utils/anchor.ts +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/utils/anchor.ts @@ -1,31 +1,34 @@ -import { BN, type IdlAccounts, Program } from '@anchor-lang/core'; -import { PublicKey } from '@solana/web3.js'; -import { type ExtensionNft, IDL } from '../idl/extension_nft'; -import { WrappedConnection } from './wrappedConnection'; - -export const CONNECTION = new WrappedConnection(process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : 'https://rpc.magicblock.app/devnet', { - wsEndpoint: process.env.NEXT_PUBLIC_WSS_RPC ? process.env.NEXT_PUBLIC_WSS_RPC : 'wss://rpc.magicblock.app/devnet', - commitment: 'confirmed', -}); +import { BN, type IdlAccounts, Program } from "@anchor-lang/core"; +import { PublicKey } from "@solana/web3.js"; +import { type ExtensionNft, IDL } from "../idl/extension_nft"; +import { WrappedConnection } from "./wrappedConnection"; + +export const CONNECTION = new WrappedConnection( + process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : "https://rpc.magicblock.app/devnet", + { + wsEndpoint: process.env.NEXT_PUBLIC_WSS_RPC ? process.env.NEXT_PUBLIC_WSS_RPC : "wss://rpc.magicblock.app/devnet", + commitment: "confirmed", + }, +); -export const METAPLEX_READAPI = 'https://devnet.helius-rpc.com/?api-key=78065db3-87fb-431c-8d43-fcd190212125'; +export const METAPLEX_READAPI = "https://devnet.helius-rpc.com/?api-key=78065db3-87fb-431c-8d43-fcd190212125"; // Here you can basically use what ever seed you want. For example one per level or city or whatever. -export const GAME_DATA_SEED = 'level_2'; +export const GAME_DATA_SEED = "level_2"; // ExtensionNft game program ID -const programId = new PublicKey('H31ofLpWqeAzF2Pg54HSPQGYifJad843tTJg8vCYVoh3'); +const programId = new PublicKey("H31ofLpWqeAzF2Pg54HSPQGYifJad843tTJg8vCYVoh3"); // Create the program interface using the idl, program ID, and provider export const program = new Program(IDL, programId, { connection: CONNECTION, }); -export const [gameDataPDA] = PublicKey.findProgramAddressSync([Buffer.from(GAME_DATA_SEED, 'utf8')], program.programId); +export const [gameDataPDA] = PublicKey.findProgramAddressSync([Buffer.from(GAME_DATA_SEED, "utf8")], program.programId); // Player Data Account Type from Idl -export type PlayerData = IdlAccounts['playerData']; -export type GameData = IdlAccounts['gameData']; +export type PlayerData = IdlAccounts["playerData"]; +export type GameData = IdlAccounts["gameData"]; // Constants for the game export const TIME_TO_REFILL_ENERGY: BN = new BN(60); diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/utils/wrappedConnection.ts b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/utils/wrappedConnection.ts index 2275dac50..a57b111e9 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/utils/wrappedConnection.ts +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/utils/wrappedConnection.ts @@ -1,14 +1,19 @@ -import { Connection } from '@solana/web3.js'; -import axios from 'axios'; -import { METAPLEX_READAPI } from './anchor'; +import { Connection } from "@solana/web3.js"; +import axios from "axios"; +import { METAPLEX_READAPI } from "./anchor"; + +interface SortBy { + sortBy: string; + sortDirection: string; +} export class WrappedConnection extends Connection { - async getAsset(assetId: any): Promise { + async getAsset(assetId: string): Promise { try { const response = await axios.post(process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : METAPLEX_READAPI, { - jsonrpc: '2.0', - method: 'getAsset', - id: 'compression-example', + jsonrpc: "2.0", + method: "getAsset", + id: "compression-example", params: [assetId], }); return response.data.result; @@ -17,12 +22,12 @@ export class WrappedConnection extends Connection { } } - async getAssetProof(assetId: any): Promise { + async getAssetProof(assetId: string): Promise { try { const response = await axios.post(process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : METAPLEX_READAPI, { - jsonrpc: '2.0', - method: 'getAssetProof', - id: 'compression-example', + jsonrpc: "2.0", + method: "getAssetProof", + id: "compression-example", params: [assetId], }); return response.data.result; @@ -31,12 +36,19 @@ export class WrappedConnection extends Connection { } } - async getAssetsByOwner(assetId: string, sortBy: any, limit: number, page: number, before: string, after: string): Promise { + async getAssetsByOwner( + assetId: string, + sortBy: SortBy, + limit: number, + page: number, + before: string, + after: string, + ): Promise { try { const response = await axios.post(process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : METAPLEX_READAPI, { - jsonrpc: '2.0', - method: 'getAssetsByOwner', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAssetsByOwner", + id: "rpd-op-123", params: [assetId, sortBy, limit, page, before, after], }); //console.log("getAssetsByOwner: " + JSON.stringify(response.data)); @@ -46,12 +58,19 @@ export class WrappedConnection extends Connection { } } - async getAssetsByCreator(assetId: string, sortBy: any, limit: number, page: number, _before: string, _after: string): Promise { + async getAssetsByCreator( + assetId: string, + sortBy: SortBy, + limit: number, + page: number, + _before: string, + _after: string, + ): Promise { try { const response = await axios.post(process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : METAPLEX_READAPI, { - jsonrpc: '2.0', - method: 'getAssetsByCreator', - id: 'compression-example', + jsonrpc: "2.0", + method: "getAssetsByCreator", + id: "compression-example", params: [assetId, true, sortBy, limit, page, null, null], }); @@ -61,12 +80,19 @@ export class WrappedConnection extends Connection { } } - async getAssetsByAuthority(assetId: string, sortBy: any, limit: number, page: number, before: string, after: string): Promise { + async getAssetsByAuthority( + assetId: string, + sortBy: SortBy, + limit: number, + page: number, + before: string, + after: string, + ): Promise { try { const response = await axios.post(process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : METAPLEX_READAPI, { - jsonrpc: '2.0', - method: 'getAssetsByAuthority', - id: 'compression-example', + jsonrpc: "2.0", + method: "getAssetsByAuthority", + id: "compression-example", params: [assetId, sortBy, limit, page, before, after], }); return response.data.result; @@ -78,19 +104,19 @@ export class WrappedConnection extends Connection { async getAssetsByGroup( groupKey: string, groupValue: string, - sortBy: any, + sortBy: SortBy, limit: number, page: number, before: string, after: string, - ): Promise { + ): Promise { try { const events = []; const response = await axios.post(process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : METAPLEX_READAPI, { - jsonrpc: '2.0', - method: 'getAssetsByGroup', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAssetsByGroup", + id: "rpd-op-123", params: [groupKey, groupValue, sortBy, limit, page, before, after], }); events.push(...response.data.result.items); @@ -105,19 +131,19 @@ export class WrappedConnection extends Connection { async getAllAssetsByGroup( groupKey: string, groupValue: string, - sortBy: any, + sortBy: SortBy, limit: number, startPage: number, before: string, after: string, - ): Promise { + ): Promise { let page = startPage; try { const events = []; let response = await axios.post(process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : METAPLEX_READAPI, { - jsonrpc: '2.0', - method: 'getAssetsByGroup', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAssetsByGroup", + id: "rpd-op-123", params: [groupKey, groupValue, sortBy, limit, page, before, after], }); @@ -128,9 +154,9 @@ export class WrappedConnection extends Connection { page += 1; response = await axios.post(process.env.NEXT_PUBLIC_RPC ? process.env.NEXT_PUBLIC_RPC : METAPLEX_READAPI, { - jsonrpc: '2.0', - method: 'getAssetsByGroup', - id: 'rpd-op-123', + jsonrpc: "2.0", + method: "getAssetsByGroup", + id: "rpd-op-123", params: [groupKey, groupValue, sortBy, limit, page, before, after], }); diff --git a/tokens/token-2022/nft-meta-data-pointer/anchor-example/unity/ExtensionNft/Assets/TextMesh Pro/Sprites/EmojiOne.json b/tokens/token-2022/nft-meta-data-pointer/anchor-example/unity/ExtensionNft/Assets/TextMesh Pro/Sprites/EmojiOne.json index 2b5e1e6a6..53663458b 100644 --- a/tokens/token-2022/nft-meta-data-pointer/anchor-example/unity/ExtensionNft/Assets/TextMesh Pro/Sprites/EmojiOne.json +++ b/tokens/token-2022/nft-meta-data-pointer/anchor-example/unity/ExtensionNft/Assets/TextMesh Pro/Sprites/EmojiOne.json @@ -1,157 +1,157 @@ { - "frames": [ - { - "filename": "1f60a.png", - "frame": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f60b.png", - "frame": { "x": 128, "y": 0, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f60d.png", - "frame": { "x": 256, "y": 0, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f60e.png", - "frame": { "x": 384, "y": 0, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f600.png", - "frame": { "x": 0, "y": 128, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f601.png", - "frame": { "x": 128, "y": 128, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f602.png", - "frame": { "x": 256, "y": 128, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f603.png", - "frame": { "x": 384, "y": 128, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f604.png", - "frame": { "x": 0, "y": 256, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f605.png", - "frame": { "x": 128, "y": 256, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f606.png", - "frame": { "x": 256, "y": 256, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f609.png", - "frame": { "x": 384, "y": 256, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f618.png", - "frame": { "x": 0, "y": 384, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "1f923.png", - "frame": { "x": 128, "y": 384, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "263a.png", - "frame": { "x": 256, "y": 384, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - }, - { - "filename": "2639.png", - "frame": { "x": 384, "y": 384, "w": 128, "h": 128 }, - "rotated": false, - "trimmed": false, - "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, - "sourceSize": { "w": 128, "h": 128 }, - "pivot": { "x": 0.5, "y": 0.5 } - } - ], - "meta": { - "app": "http://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "EmojiOne.png", - "format": "RGBA8888", - "size": { "w": 512, "h": 512 }, - "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:196a26a2e149d875b91ffc8fa3581e76:fc928c7e275404b7e0649307410475cb:424723c3774975ddb2053fd5c4b85f6e$" - } + "frames": [ + { + "filename": "1f60a.png", + "frame": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f60b.png", + "frame": { "x": 128, "y": 0, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f60d.png", + "frame": { "x": 256, "y": 0, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f60e.png", + "frame": { "x": 384, "y": 0, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f600.png", + "frame": { "x": 0, "y": 128, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f601.png", + "frame": { "x": 128, "y": 128, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f602.png", + "frame": { "x": 256, "y": 128, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f603.png", + "frame": { "x": 384, "y": 128, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f604.png", + "frame": { "x": 0, "y": 256, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f605.png", + "frame": { "x": 128, "y": 256, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f606.png", + "frame": { "x": 256, "y": 256, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f609.png", + "frame": { "x": 384, "y": 256, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f618.png", + "frame": { "x": 0, "y": 384, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "1f923.png", + "frame": { "x": 128, "y": 384, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "263a.png", + "frame": { "x": 256, "y": 384, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + }, + { + "filename": "2639.png", + "frame": { "x": 384, "y": 384, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "pivot": { "x": 0.5, "y": 0.5 } + } + ], + "meta": { + "app": "http://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "EmojiOne.png", + "format": "RGBA8888", + "size": { "w": 512, "h": 512 }, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:196a26a2e149d875b91ffc8fa3581e76:fc928c7e275404b7e0649307410475cb:424723c3774975ddb2053fd5c4b85f6e$" + } } diff --git a/tokens/token-2022/non-transferable/anchor/Anchor.toml b/tokens/token-2022/non-transferable/anchor/Anchor.toml index ff3f4fc51..5200062d6 100644 --- a/tokens/token-2022/non-transferable/anchor/Anchor.toml +++ b/tokens/token-2022/non-transferable/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -non_transferable = "8Bz4wpHaUckiC169Rg5ZfaBHFemp5S8RwTSDTKzhJ9W" - -# [registry] section removed — no longer used in Anchor 1.0 +non_transferable = "9GpYDDJUM7CCrruDsg9v1aff5BouEzGfXifu8Woyhnbn" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/non-transferable/anchor/migrations/deploy.ts b/tokens/token-2022/non-transferable/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/non-transferable/anchor/migrations/deploy.ts +++ b/tokens/token-2022/non-transferable/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/non-transferable/anchor/package.json b/tokens/token-2022/non-transferable/anchor/package.json index f800607c4..cc320fb64 100644 --- a/tokens/token-2022/non-transferable/anchor/package.json +++ b/tokens/token-2022/non-transferable/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/non-transferable/anchor/pnpm-lock.yaml b/tokens/token-2022/non-transferable/anchor/pnpm-lock.yaml index 841b2d24e..349da1833 100644 --- a/tokens/token-2022/non-transferable/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/non-transferable/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.6 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -860,16 +860,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -887,7 +887,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/non-transferable/anchor/programs/non-transferable/Cargo.toml b/tokens/token-2022/non-transferable/anchor/programs/non-transferable/Cargo.toml index 749c0e75b..b06a6f980 100644 --- a/tokens/token-2022/non-transferable/anchor/programs/non-transferable/Cargo.toml +++ b/tokens/token-2022/non-transferable/anchor/programs/non-transferable/Cargo.toml @@ -17,5 +17,12 @@ no-log-ix-name = [] idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] [dependencies] -anchor-lang = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" diff --git a/tokens/token-2022/non-transferable/anchor/programs/non-transferable/src/lib.rs b/tokens/token-2022/non-transferable/anchor/programs/non-transferable/src/lib.rs index 05d096f72..65e8b142c 100644 --- a/tokens/token-2022/non-transferable/anchor/programs/non-transferable/src/lib.rs +++ b/tokens/token-2022/non-transferable/anchor/programs/non-transferable/src/lib.rs @@ -9,7 +9,7 @@ use anchor_spl::{ token_interface::{non_transferable_mint_initialize, NonTransferableMintInitialize, Token2022}, }; -declare_id!("8Bz4wpHaUckiC169Rg5ZfaBHFemp5S8RwTSDTKzhJ9W"); +declare_id!("9GpYDDJUM7CCrruDsg9v1aff5BouEzGfXifu8Woyhnbn"); #[program] pub mod non_transferable { diff --git a/tokens/token-2022/non-transferable/anchor/programs/non-transferable/tests/test_non_transferable.rs b/tokens/token-2022/non-transferable/anchor/programs/non-transferable/tests/test_non_transferable.rs new file mode 100644 index 000000000..3ec60c6bb --- /dev/null +++ b/tokens/token-2022/non-transferable/anchor/programs/non-transferable/tests/test_non_transferable.rs @@ -0,0 +1,107 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::Instruction, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_account, get_token_extensions_account_address, + mint_tokens_to_token_extensions_account, transfer_checked_token_extensions, + TOKEN_EXTENSIONS_PROGRAM_ID, + }, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = non_transferable::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/non_transferable.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_create_non_transferable_mint_and_attempt_transfer() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + + // Step 1: Create mint with NonTransferable extension via our program + let initialize_ix = Instruction::new_with_bytes( + program_id, + &non_transferable::instruction::Initialize {}.data(), + non_transferable::accounts::Initialize { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Verify mint account was created and has extension data + let mint_data = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint account should exist"); + assert!( + mint_data.data.len() > 82, + "Mint should have extension data (size > 82, got {})", + mint_data.data.len() + ); + + // Step 2: Create ATAs for sender and recipient + let recipient = Keypair::new(); + let source_ata = create_token_extensions_account( + &mut svm, + &payer.pubkey(), + &mint_keypair.pubkey(), + &payer, + ).unwrap(); + svm.expire_blockhash(); + + let dest_ata = create_token_extensions_account( + &mut svm, + &recipient.pubkey(), + &mint_keypair.pubkey(), + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 3: Mint 1 token to sender + mint_tokens_to_token_extensions_account( + &mut svm, + &mint_keypair.pubkey(), + &source_ata, + 1, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 4: Attempt transfer — should fail because mint is NonTransferable + let result = transfer_checked_token_extensions( + &mut svm, + &source_ata, + &mint_keypair.pubkey(), + &dest_ata, + &payer, + 1, + 2, // decimals + &[], + ); + assert!( + result.is_err(), + "Transfer should fail because the mint is non-transferable" + ); +} diff --git a/tokens/token-2022/non-transferable/anchor/tests/non-transferable.ts b/tokens/token-2022/non-transferable/anchor/tests/non-transferable.ts index 112a9eb13..414c651d2 100644 --- a/tokens/token-2022/non-transferable/anchor/tests/non-transferable.ts +++ b/tokens/token-2022/non-transferable/anchor/tests/non-transferable.ts @@ -1,9 +1,15 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { ASSOCIATED_TOKEN_PROGRAM_ID, getOrCreateAssociatedTokenAccount, mintTo, TOKEN_2022_PROGRAM_ID, transfer } from '@solana/spl-token'; -import type { NonTransferable } from '../target/types/non_transferable'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + getOrCreateAssociatedTokenAccount, + mintTo, + TOKEN_2022_PROGRAM_ID, + transfer, +} from "@solana/spl-token"; +import type { NonTransferable } from "../target/types/non_transferable"; -describe('non-transferable', () => { +describe("non-transferable", () => { const provider = anchor.AnchorProvider.env(); const connection = provider.connection; const wallet = provider.wallet as anchor.Wallet; @@ -14,16 +20,16 @@ describe('non-transferable', () => { const mintKeypair = new anchor.web3.Keypair(); const recipient = new anchor.web3.Keypair(); - it('Create Mint with NonTransferable extension', async () => { + it("Create Mint with NonTransferable extension", async () => { const transactionSignature = await program.methods .initialize() .accounts({ mintAccount: mintKeypair.publicKey }) .signers([mintKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Attempt Token Transfer', async () => { + it("Attempt Token Transfer", async () => { const amount = 1; const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( @@ -76,7 +82,7 @@ describe('non-transferable', () => { TOKEN_2022_PROGRAM_ID, // Token Extension Program ID ); } catch (error) { - console.log('\nExpect Error:', error.logs); + console.log("\nExpect Error:", error.logs); } }); }); diff --git a/tokens/token-2022/non-transferable/native/tests/test.ts b/tokens/token-2022/non-transferable/native/tests/test.ts index 8b67b66b2..c9c0fc870 100644 --- a/tokens/token-2022/non-transferable/native/tests/test.ts +++ b/tokens/token-2022/non-transferable/native/tests/test.ts @@ -1,25 +1,31 @@ -import { Buffer } from 'node:buffer'; -import { describe, test } from 'node:test'; -import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import { Keypair, PublicKey, SYSVAR_RENT_PUBKEY, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { assert } from 'chai'; -import { start } from 'solana-bankrun'; - - -const CreateTokenArgsSchema = { struct: { token_decimals: 'u8' } }; +import { Buffer } from "node:buffer"; +import { describe, test } from "node:test"; +import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import { + Keypair, + PublicKey, + SYSVAR_RENT_PUBKEY, + SystemProgram, + Transaction, + TransactionInstruction, +} from "@solana/web3.js"; +import * as borsh from "borsh"; +import { assert } from "chai"; +import { start } from "solana-bankrun"; + +const CreateTokenArgsSchema = { struct: { token_decimals: "u8" } }; function borshSerialize(schema: borsh.Schema, data: object): Buffer { return Buffer.from(borsh.serialize(schema, data)); } -describe('Create Token', async () => { +describe("Create Token", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'token_2022_non_transferable_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "token_2022_non_transferable_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; - test('Create a Token-22 SPL-Token !', async () => { + test("Create a Token-22 SPL-Token !", async () => { const blockhash = context.lastBlockhash; const mintKeypair: Keypair = Keypair.generate(); @@ -47,6 +53,6 @@ describe('Create Token', async () => { const transaction = await client.processTransaction(tx); assert(transaction.logMessages[0].startsWith(`Program ${PROGRAM_ID}`)); - console.log('Token Mint Address: ', mintKeypair.publicKey.toBase58()); + console.log("Token Mint Address: ", mintKeypair.publicKey.toBase58()); }); }); diff --git a/tokens/token-2022/permanent-delegate/anchor/Anchor.toml b/tokens/token-2022/permanent-delegate/anchor/Anchor.toml index 5482905c8..747c431bc 100644 --- a/tokens/token-2022/permanent-delegate/anchor/Anchor.toml +++ b/tokens/token-2022/permanent-delegate/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -permanent_delegate = "A9rxKS84ZoJVyeTfQbCEfxME2vvAM4uwSMjkmhR5XWb1" - -# [registry] section removed — no longer used in Anchor 1.0 +permanent_delegate = "g63s55bPYTvuuXFRMCzDaKTjCnXhDPNmwjafnQUNexa" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/permanent-delegate/anchor/migrations/deploy.ts b/tokens/token-2022/permanent-delegate/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/permanent-delegate/anchor/migrations/deploy.ts +++ b/tokens/token-2022/permanent-delegate/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/permanent-delegate/anchor/package.json b/tokens/token-2022/permanent-delegate/anchor/package.json index f800607c4..cc320fb64 100644 --- a/tokens/token-2022/permanent-delegate/anchor/package.json +++ b/tokens/token-2022/permanent-delegate/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/permanent-delegate/anchor/pnpm-lock.yaml b/tokens/token-2022/permanent-delegate/anchor/pnpm-lock.yaml index 841b2d24e..349da1833 100644 --- a/tokens/token-2022/permanent-delegate/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/permanent-delegate/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.6 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -860,16 +860,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -887,7 +887,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/Cargo.toml b/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/Cargo.toml index 41b66d80e..0640343cb 100644 --- a/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/Cargo.toml +++ b/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/Cargo.toml @@ -21,8 +21,15 @@ custom-panic = [] [dependencies] -anchor-lang = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/src/lib.rs b/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/src/lib.rs index 76f03648b..2d181361f 100644 --- a/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/src/lib.rs +++ b/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/src/lib.rs @@ -11,7 +11,7 @@ use anchor_spl::{ }, }; -declare_id!("A9rxKS84ZoJVyeTfQbCEfxME2vvAM4uwSMjkmhR5XWb1"); +declare_id!("g63s55bPYTvuuXFRMCzDaKTjCnXhDPNmwjafnQUNexa"); #[program] pub mod permanent_delegate { diff --git a/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/tests/test_permanent_delegate.rs b/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/tests/test_permanent_delegate.rs new file mode 100644 index 000000000..894f3f17f --- /dev/null +++ b/tokens/token-2022/permanent-delegate/anchor/programs/permanent-delegate/tests/test_permanent_delegate.rs @@ -0,0 +1,134 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + assert_token_account_balance, create_wallet, send_transaction_from_instructions, + token_extensions::{ + mint_tokens_to_token_extensions_account, TOKEN_EXTENSIONS_PROGRAM_ID, + }, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = permanent_delegate::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/permanent_delegate.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +/// Create a Token Extensions token account (CreateAccount + InitializeAccount3). +/// This creates a non-ATA token account with explicit keypair, which kite doesn't provide. +fn create_token_account_instructions( + payer: &Pubkey, + account: &Pubkey, + mint: &Pubkey, + owner: &Pubkey, +) -> Vec { + let space: u64 = 200; + let lamports: u64 = 3_000_000; + let create_account_ix = anchor_lang::solana_program::system_instruction::create_account( + payer, account, lamports, space, &TOKEN_EXTENSIONS_PROGRAM_ID, + ); + // InitializeAccount3 (instruction 18): [18, owner(32)] + let mut init_data = vec![18u8]; + init_data.extend_from_slice(owner.as_ref()); + let init_account_ix = Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*account, false), + AccountMeta::new_readonly(*mint, false), + ], + data: init_data, + }; + vec![create_account_ix, init_account_ix] +} + +/// BurnChecked instruction for Token Extensions (instruction 15). +fn burn_checked_ix( + account: &Pubkey, + mint: &Pubkey, + authority: &Pubkey, + amount: u64, + decimals: u8, +) -> Instruction { + let mut data = vec![15u8]; + data.extend_from_slice(&amount.to_le_bytes()); + data.push(decimals); + Instruction { + program_id: TOKEN_EXTENSIONS_PROGRAM_ID, + accounts: vec![ + AccountMeta::new(*account, false), + AccountMeta::new(*mint, false), + AccountMeta::new_readonly(*authority, true), + ], + data, + } +} + +#[test] +fn test_create_mint_with_permanent_delegate_and_burn() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + + // Step 1: Create mint with PermanentDelegate extension via program + let initialize_ix = Instruction::new_with_bytes( + program_id, + &permanent_delegate::instruction::Initialize {}.data(), + permanent_delegate::accounts::Initialize { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 2: Create a token account owned by a random keypair + let random_owner = Keypair::new(); + let token_account = Keypair::new(); + let create_ata_ixs = create_token_account_instructions( + &payer.pubkey(), + &token_account.pubkey(), + &mint_keypair.pubkey(), + &random_owner.pubkey(), + ); + send_transaction_from_instructions(&mut svm, create_ata_ixs, &[&payer, &token_account], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 3: Mint 100 tokens to the token account + mint_tokens_to_token_extensions_account( + &mut svm, + &mint_keypair.pubkey(), + &token_account.pubkey(), + 100, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 4: Burn all 100 tokens using the permanent delegate (payer) + let burn_ix = burn_checked_ix( + &token_account.pubkey(), + &mint_keypair.pubkey(), + &payer.pubkey(), + 100, + 2, // decimals + ); + send_transaction_from_instructions(&mut svm, vec![burn_ix], &[&payer], &payer.pubkey()).unwrap(); + + assert_token_account_balance(&svm, &token_account.pubkey(), 0, "Token account balance should be 0 after burn"); +} diff --git a/tokens/token-2022/permanent-delegate/anchor/tests/permanent-delegate.ts b/tokens/token-2022/permanent-delegate/anchor/tests/permanent-delegate.ts index 0c9da2467..38d77576a 100644 --- a/tokens/token-2022/permanent-delegate/anchor/tests/permanent-delegate.ts +++ b/tokens/token-2022/permanent-delegate/anchor/tests/permanent-delegate.ts @@ -1,9 +1,9 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { burnChecked, createAccount, getAccount, mintTo, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import type { PermanentDelegate } from '../target/types/permanent_delegate'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { burnChecked, createAccount, getAccount, mintTo, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import type { PermanentDelegate } from "../target/types/permanent_delegate"; -describe('permanent-delegate', () => { +describe("permanent-delegate", () => { const provider = anchor.AnchorProvider.env(); const connection = provider.connection; const wallet = provider.wallet as anchor.Wallet; @@ -13,16 +13,16 @@ describe('permanent-delegate', () => { const mintKeypair = new anchor.web3.Keypair(); - it('Create Mint with Permanent Delegate', async () => { + it("Create Mint with Permanent Delegate", async () => { const transactionSignature = await program.methods .initialize() .accounts({ mintAccount: mintKeypair.publicKey }) .signers([mintKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Create Token Account, Mint Tokens, and burn with Permanent Delegate', async () => { + it("Create Token Account, Mint Tokens, and burn with Permanent Delegate", async () => { const amount = 100; // Random keypair to use as owner of Token Account @@ -66,9 +66,9 @@ describe('permanent-delegate', () => { undefined, // Confirmation options TOKEN_2022_PROGRAM_ID, // Token Extension Program ID ); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); const tokenAccount = await getAccount(connection, sourceTokenAccount, null, TOKEN_2022_PROGRAM_ID); - console.log('Token Account Balance:', Number(tokenAccount.amount)); + console.log("Token Account Balance:", Number(tokenAccount.amount)); }); }); diff --git a/tokens/token-2022/transfer-fee/anchor/Anchor.toml b/tokens/token-2022/transfer-fee/anchor/Anchor.toml index 6759948ba..2275a32dc 100644 --- a/tokens/token-2022/transfer-fee/anchor/Anchor.toml +++ b/tokens/token-2022/transfer-fee/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -transfer_fee = "4evptdGtALCNT8uTxJhbWBRZpBE8w5oNtmgfSyfQu7td" - -# [registry] section removed — no longer used in Anchor 1.0 +transfer_fee = "FRB5Ln5fbH4sA1dyJRZz9M5mXQij8Tfr4cKtnP3gNaC1" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/transfer-fee/anchor/migrations/deploy.ts b/tokens/token-2022/transfer-fee/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/transfer-fee/anchor/migrations/deploy.ts +++ b/tokens/token-2022/transfer-fee/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/transfer-fee/anchor/package.json b/tokens/token-2022/transfer-fee/anchor/package.json index f800607c4..cc320fb64 100644 --- a/tokens/token-2022/transfer-fee/anchor/package.json +++ b/tokens/token-2022/transfer-fee/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/transfer-fee/anchor/pnpm-lock.yaml b/tokens/token-2022/transfer-fee/anchor/pnpm-lock.yaml index 841b2d24e..349da1833 100644 --- a/tokens/token-2022/transfer-fee/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/transfer-fee/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.6 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -860,16 +860,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -887,7 +887,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/Cargo.toml b/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/Cargo.toml index a3ac9f655..c29fae100 100644 --- a/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/Cargo.toml +++ b/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/Cargo.toml @@ -17,5 +17,12 @@ no-log-ix-name = [] idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] [dependencies] -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" diff --git a/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/src/lib.rs b/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/src/lib.rs index f264757c3..38365fea9 100644 --- a/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/src/lib.rs +++ b/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/src/lib.rs @@ -3,7 +3,7 @@ use anchor_lang::prelude::*; mod instructions; use instructions::*; -declare_id!("4evptdGtALCNT8uTxJhbWBRZpBE8w5oNtmgfSyfQu7td"); +declare_id!("FRB5Ln5fbH4sA1dyJRZz9M5mXQij8Tfr4cKtnP3gNaC1"); #[program] pub mod transfer_fee { diff --git a/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/tests/test_transfer_fee.rs b/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/tests/test_transfer_fee.rs new file mode 100644 index 000000000..5a734aa50 --- /dev/null +++ b/tokens/token-2022/transfer-fee/anchor/programs/transfer-fee/tests/test_transfer_fee.rs @@ -0,0 +1,172 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_account, get_token_extensions_account_address, + mint_tokens_to_token_extensions_account, TOKEN_EXTENSIONS_PROGRAM_ID, + }, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn associated_token_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = transfer_fee::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/transfer_fee.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_transfer_fee_full_flow() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + let recipient = Keypair::new(); + let ata_program = associated_token_program_id(); + + let sender_ata = get_token_extensions_account_address(&payer.pubkey(), &mint_keypair.pubkey()); + let recipient_ata = get_token_extensions_account_address(&recipient.pubkey(), &mint_keypair.pubkey()); + + // Step 1: Create mint with transfer fee (100 basis points = 1%, max fee = 1) + let initialize_ix = Instruction::new_with_bytes( + program_id, + &transfer_fee::instruction::Initialize { + transfer_fee_basis_points: 100, + maximum_fee: 1, + } + .data(), + transfer_fee::accounts::Initialize { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 2: Create sender ATA and mint 300 tokens + create_token_extensions_account( + &mut svm, + &payer.pubkey(), + &mint_keypair.pubkey(), + &payer, + ).unwrap(); + svm.expire_blockhash(); + + mint_tokens_to_token_extensions_account( + &mut svm, + &mint_keypair.pubkey(), + &sender_ata, + 300, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 3: Transfer 100 tokens (fee = min(1% * 100 = 1, max_fee = 1) = 1) + let transfer_ix = Instruction::new_with_bytes( + program_id, + &transfer_fee::instruction::Transfer { amount: 100 }.data(), + transfer_fee::accounts::Transfer { + sender: payer.pubkey(), + recipient: recipient.pubkey(), + mint_account: mint_keypair.pubkey(), + sender_token_account: sender_ata, + recipient_token_account: recipient_ata, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + associated_token_program: ata_program, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![transfer_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 4: Transfer 200 tokens (fee = min(1% * 200 = 2, max_fee = 1) = 1, capped by maximumFee) + let transfer_ix2 = Instruction::new_with_bytes( + program_id, + &transfer_fee::instruction::Transfer { amount: 200 }.data(), + transfer_fee::accounts::Transfer { + sender: payer.pubkey(), + recipient: recipient.pubkey(), + mint_account: mint_keypair.pubkey(), + sender_token_account: sender_ata, + recipient_token_account: recipient_ata, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + associated_token_program: ata_program, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![transfer_ix2], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 5: Harvest transfer fees from recipient token account to mint + let harvest_ix = Instruction::new_with_bytes( + program_id, + &transfer_fee::instruction::Harvest {}.data(), + { + let mut metas = transfer_fee::accounts::Harvest { + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + } + .to_account_metas(None); + metas.push(AccountMeta::new(recipient_ata, false)); + metas + }, + ); + send_transaction_from_instructions(&mut svm, vec![harvest_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 6: Withdraw harvested fees from mint to sender's token account + let withdraw_ix = Instruction::new_with_bytes( + program_id, + &transfer_fee::instruction::Withdraw {}.data(), + transfer_fee::accounts::Withdraw { + authority: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_account: sender_ata, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![withdraw_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 7: Update transfer fee to 0 + let update_fee_ix = Instruction::new_with_bytes( + program_id, + &transfer_fee::instruction::UpdateFee { + transfer_fee_basis_points: 0, + maximum_fee: 0, + } + .data(), + transfer_fee::accounts::UpdateFee { + authority: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![update_fee_ix], &[&payer], &payer.pubkey()).unwrap(); +} diff --git a/tokens/token-2022/transfer-fee/anchor/tests/transfer-fee.ts b/tokens/token-2022/transfer-fee/anchor/tests/transfer-fee.ts index e717fb53a..78726bc74 100644 --- a/tokens/token-2022/transfer-fee/anchor/tests/transfer-fee.ts +++ b/tokens/token-2022/transfer-fee/anchor/tests/transfer-fee.ts @@ -1,10 +1,15 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { ASSOCIATED_PROGRAM_ID } from '@anchor-lang/core/dist/cjs/utils/token'; -import { getAssociatedTokenAddressSync, getOrCreateAssociatedTokenAccount, mintTo, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import type { TransferFee } from '../target/types/transfer_fee'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { ASSOCIATED_PROGRAM_ID } from "@anchor-lang/core/dist/cjs/utils/token"; +import { + getAssociatedTokenAddressSync, + getOrCreateAssociatedTokenAccount, + mintTo, + TOKEN_2022_PROGRAM_ID, +} from "@solana/spl-token"; +import type { TransferFee } from "../target/types/transfer_fee"; -describe('transfer-fee', () => { +describe("transfer-fee", () => { const provider = anchor.AnchorProvider.env(); const connection = provider.connection; const wallet = provider.wallet as anchor.Wallet; @@ -15,11 +20,21 @@ describe('transfer-fee', () => { const mintKeypair = new anchor.web3.Keypair(); const recipient = new anchor.web3.Keypair(); - const senderTokenAccountAddress = getAssociatedTokenAddressSync(mintKeypair.publicKey, wallet.publicKey, false, TOKEN_2022_PROGRAM_ID); + const senderTokenAccountAddress = getAssociatedTokenAddressSync( + mintKeypair.publicKey, + wallet.publicKey, + false, + TOKEN_2022_PROGRAM_ID, + ); - const recipientTokenAccountAddress = getAssociatedTokenAddressSync(mintKeypair.publicKey, recipient.publicKey, false, TOKEN_2022_PROGRAM_ID); + const recipientTokenAccountAddress = getAssociatedTokenAddressSync( + mintKeypair.publicKey, + recipient.publicKey, + false, + TOKEN_2022_PROGRAM_ID, + ); - it('Create Mint with Transfer Fee', async () => { + it("Create Mint with Transfer Fee", async () => { const transferFeeBasisPoints = 100; const maximumFee = 1; @@ -28,10 +43,10 @@ describe('transfer-fee', () => { .accounts({ mintAccount: mintKeypair.publicKey }) .signers([mintKeypair]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Mint Tokens', async () => { + it("Mint Tokens", async () => { await getOrCreateAssociatedTokenAccount( connection, wallet.payer, @@ -44,10 +59,20 @@ describe('transfer-fee', () => { ASSOCIATED_PROGRAM_ID, ); - await mintTo(connection, wallet.payer, mintKeypair.publicKey, senderTokenAccountAddress, wallet.payer, 300, [], null, TOKEN_2022_PROGRAM_ID); + await mintTo( + connection, + wallet.payer, + mintKeypair.publicKey, + senderTokenAccountAddress, + wallet.payer, + 300, + [], + null, + TOKEN_2022_PROGRAM_ID, + ); }); - it('Transfer', async () => { + it("Transfer", async () => { const transactionSignature = await program.methods .transfer(new anchor.BN(100)) .accounts({ @@ -58,10 +83,10 @@ describe('transfer-fee', () => { recipientTokenAccount: recipientTokenAccountAddress, }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Transfer Again, fee limit by maximumFee', async () => { + it("Transfer Again, fee limit by maximumFee", async () => { const transactionSignature = await program.methods .transfer(new anchor.BN(200)) .accounts({ @@ -72,10 +97,10 @@ describe('transfer-fee', () => { recipientTokenAccount: recipientTokenAccountAddress, }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Harvest Transfer Fees to Mint Account', async () => { + it("Harvest Transfer Fees to Mint Account", async () => { const transactionSignature = await program.methods .harvest() .accounts({ mintAccount: mintKeypair.publicKey }) @@ -87,10 +112,10 @@ describe('transfer-fee', () => { }, ]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Withdraw Transfer Fees from Mint Account', async () => { + it("Withdraw Transfer Fees from Mint Account", async () => { const transactionSignature = await program.methods .withdraw() .accounts({ @@ -98,10 +123,10 @@ describe('transfer-fee', () => { tokenAccount: senderTokenAccountAddress, }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); - it('Update Transfer Fee', async () => { + it("Update Transfer Fee", async () => { const transferFeeBasisPoints = 0; const maximumFee = 0; @@ -109,6 +134,6 @@ describe('transfer-fee', () => { .updateFee(transferFeeBasisPoints, new anchor.BN(maximumFee)) .accounts({ mintAccount: mintKeypair.publicKey }) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); }); diff --git a/tokens/token-2022/transfer-fee/native/tests/test.ts b/tokens/token-2022/transfer-fee/native/tests/test.ts index c0f846883..e6cde2528 100644 --- a/tokens/token-2022/transfer-fee/native/tests/test.ts +++ b/tokens/token-2022/transfer-fee/native/tests/test.ts @@ -1,25 +1,31 @@ -import { Buffer } from 'node:buffer'; -import { describe, test } from 'node:test'; -import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; -import { Keypair, PublicKey, SYSVAR_RENT_PUBKEY, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js'; -import * as borsh from 'borsh'; -import { assert } from 'chai'; -import { start } from 'solana-bankrun'; - - -const CreateTokenArgsSchema = { struct: { token_decimals: 'u8' } }; +import { Buffer } from "node:buffer"; +import { describe, test } from "node:test"; +import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; +import { + Keypair, + PublicKey, + SYSVAR_RENT_PUBKEY, + SystemProgram, + Transaction, + TransactionInstruction, +} from "@solana/web3.js"; +import * as borsh from "borsh"; +import { assert } from "chai"; +import { start } from "solana-bankrun"; + +const CreateTokenArgsSchema = { struct: { token_decimals: "u8" } }; function borshSerialize(schema: borsh.Schema, data: object): Buffer { return Buffer.from(borsh.serialize(schema, data)); } -describe('Create Token', async () => { +describe("Create Token", async () => { const PROGRAM_ID = PublicKey.unique(); - const context = await start([{ name: 'token_2022_transfer_fees_program', programId: PROGRAM_ID }], []); + const context = await start([{ name: "token_2022_transfer_fees_program", programId: PROGRAM_ID }], []); const client = context.banksClient; const payer = context.payer; - test('Create a Token-22 SPL-Token !', async () => { + test("Create a Token-22 SPL-Token !", async () => { const blockhash = context.lastBlockhash; const mintKeypair: Keypair = Keypair.generate(); @@ -47,6 +53,6 @@ describe('Create Token', async () => { const transaction = await client.processTransaction(tx); assert(transaction.logMessages[0].startsWith(`Program ${PROGRAM_ID}`)); - console.log('Token Mint Address: ', mintKeypair.publicKey.toBase58()); + console.log("Token Mint Address: ", mintKeypair.publicKey.toBase58()); }); }); diff --git a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/.prettierrc b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/.prettierrc deleted file mode 100644 index d2f009f9d..000000000 --- a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "tabWidth": 2, - "useTabs": false, - "singleQuote": false, - "printWidth": 80, - "trailingComma": "all", - "arrowParens": "avoid", - "endOfLine": "auto", - "proseWrap": "always" -} diff --git a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/Anchor.toml b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/Anchor.toml index 3ad7e2a52..1907597b1 100644 --- a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/Anchor.toml +++ b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -transfer_hook = "1qahDxKHeCLZhbBU2NyMU6vQCQmEUmdeSEBrG5drffK" - -# [registry] section removed — no longer used in Anchor 1.0 +transfer_hook = "9H8q3XCs1iCCPV7bshK88geGPQQ5jMPySbyNa35ctHyF" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 100000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/migrations/deploy.ts b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/migrations/deploy.ts +++ b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/package.json b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/package.json index 3c254f5f9..466b8ee71 100644 --- a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/package.json +++ b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/package.json @@ -1,24 +1,24 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.0", - "@solana/web3.js": "^1.98.4" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/chai-as-promised": "^7.1.8", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.2", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.0", + "@solana/web3.js": "^1.98.4" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/chai-as-promised": "^7.1.8", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "chai-as-promised": "^7.1.2", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/pnpm-lock.yaml b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/pnpm-lock.yaml index 17b058e96..fc594a80b 100644 --- a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) '@solana/spl-token': specifier: ^0.4.0 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@6.0.6) @@ -51,18 +51,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.29.2': @@ -797,16 +797,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 @@ -824,7 +824,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.29.2': {} diff --git a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/Cargo.toml b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/Cargo.toml index ff4cc96fd..841067236 100644 --- a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/Cargo.toml +++ b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/Cargo.toml @@ -20,12 +20,18 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" -anchor-spl = "1.0.0-rc.5" +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" spl-discriminator = "0.4.1" spl-tlv-account-resolution = "0.9.0" spl-transfer-hook-interface = "0.9.0" +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/src/lib.rs b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/src/lib.rs index c485708a6..44db67886 100644 --- a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/src/lib.rs +++ b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/src/lib.rs @@ -23,7 +23,7 @@ use spl_transfer_hook_interface::instruction::{ ExecuteInstruction, InitializeExtraAccountMetaListInstruction, }; -declare_id!("1qahDxKHeCLZhbBU2NyMU6vQCQmEUmdeSEBrG5drffK"); +declare_id!("9H8q3XCs1iCCPV7bshK88geGPQQ5jMPySbyNa35ctHyF"); #[error_code] pub enum TransferError { diff --git a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/tests/test_transfer_hook.rs b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/tests/test_transfer_hook.rs new file mode 100644 index 000000000..4bcf15b17 --- /dev/null +++ b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/programs/transfer-hook/tests/test_transfer_hook.rs @@ -0,0 +1,154 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::Instruction, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_account, create_token_extensions_mint, + mint_tokens_to_token_extensions_account, transfer_checked_token_extensions, + MintExtension, TOKEN_EXTENSIONS_PROGRAM_ID, + }, + transfer_hook::{build_hook_accounts, get_hook_accounts_address, HookAccount}, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn associated_token_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = transfer_hook::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/transfer_hook.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_transfer_hook_account_data_as_seed() { + let (mut svm, program_id, payer) = setup(); + let recipient = Keypair::new(); + let decimals: u8 = 9; + + // PDAs + let (counter_pda, _) = + Pubkey::find_program_address(&[b"counter", payer.pubkey().as_ref()], &program_id); + + // Step 1: Create mint with TransferHook extension + let mint = create_token_extensions_mint( + &mut svm, + &payer, + decimals, + None, + &[MintExtension::TransferHook { + program_id: program_id, + }], + ) + .unwrap(); + svm.expire_blockhash(); + + let extra_account_meta_list = + get_hook_accounts_address(&mint, &program_id); + + // Step 2: Create token accounts and mint tokens + let amount: u64 = 100 * 10u64.pow(decimals as u32); + let source_ata = create_token_extensions_account( + &mut svm, + &payer.pubkey(), + &mint, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + let dest_ata = create_token_extensions_account( + &mut svm, + &recipient.pubkey(), + &mint, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + mint_tokens_to_token_extensions_account( + &mut svm, + &mint, + &source_ata, + amount, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 3: Initialize ExtraAccountMetaList (also creates counter PDA) + let init_extra_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::InitializeExtraAccountMetaList {}.data(), + transfer_hook::accounts::InitializeExtraAccountMetaList { + payer: payer.pubkey(), + extra_account_meta_list, + mint, + counter_account: counter_pda, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + associated_token_program: associated_token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_extra_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 4: Transfer with hook + let transfer_amount: u64 = 1 * 10u64.pow(decimals as u32); + let extra_accounts = build_hook_accounts( + &mint, + &program_id, + &[HookAccount { + pubkey: counter_pda, + is_signer: false, + is_writable: true, + }], + ); + transfer_checked_token_extensions( + &mut svm, + &source_ata, + &mint, + &dest_ata, + &payer, + transfer_amount, + decimals, + &extra_accounts, + ).unwrap(); + svm.expire_blockhash(); + + // Step 5: Try calling transfer_hook directly (should fail — not transferring) + let direct_hook_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::TransferHook { amount: 1 }.data(), + transfer_hook::accounts::TransferHook { + source_token: source_ata, + mint, + destination_token: dest_ata, + owner: payer.pubkey(), + extra_account_meta_list, + counter_account: counter_pda, + } + .to_account_metas(None), + ); + let result = send_transaction_from_instructions(&mut svm, vec![direct_hook_ix], &[&payer], &payer.pubkey()); + assert!( + result.is_err(), + "Calling transfer_hook directly should fail because token is not transferring" + ); +} diff --git a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/tests/transfer-hook.ts b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/tests/transfer-hook.ts index cac2820fe..b13374d8c 100644 --- a/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/tests/transfer-hook.ts +++ b/tokens/token-2022/transfer-hook/account-data-as-seed/anchor/tests/transfer-hook.ts @@ -1,5 +1,5 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; import { ASSOCIATED_TOKEN_PROGRAM_ID, createAssociatedTokenAccountInstruction, @@ -11,16 +11,23 @@ import { getAssociatedTokenAddressSync, getMintLen, TOKEN_2022_PROGRAM_ID, -} from '@solana/spl-token'; -import { Keypair, PublicKey, SendTransactionError, SystemProgram, sendAndConfirmTransaction, Transaction } from '@solana/web3.js'; -import { BN } from 'bn.js'; -import chai, { expect } from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import type { TransferHook } from '../target/types/transfer_hook'; +} from "@solana/spl-token"; +import { + Keypair, + PublicKey, + SendTransactionError, + SystemProgram, + sendAndConfirmTransaction, + Transaction, +} from "@solana/web3.js"; +import { BN } from "bn.js"; +import chai, { expect } from "chai"; +import chaiAsPromised from "chai-as-promised"; +import type { TransferHook } from "../target/types/transfer_hook"; chai.use(chaiAsPromised); -describe('transfer-hook', () => { +describe("transfer-hook", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); @@ -55,13 +62,16 @@ describe('transfer-hook', () => { // ExtraAccountMetaList address // Store extra accounts required by the custom transfer hook instruction const [extraAccountMetaListPDA] = PublicKey.findProgramAddressSync( - [Buffer.from('extra-account-metas'), mint.publicKey.toBuffer()], + [Buffer.from("extra-account-metas"), mint.publicKey.toBuffer()], program.programId, ); - const [counterPDA] = PublicKey.findProgramAddressSync([Buffer.from('counter'), wallet.publicKey.toBuffer()], program.programId); + const [counterPDA] = PublicKey.findProgramAddressSync( + [Buffer.from("counter"), wallet.publicKey.toBuffer()], + program.programId, + ); - it('Create Mint Account with Transfer Hook Extension', async () => { + it("Create Mint Account with Transfer Hook Extension", async () => { const extensions = [ExtensionType.TransferHook]; const mintLen = getMintLen(extensions); const lamports = await provider.connection.getMinimumBalanceForRentExemption(mintLen); @@ -85,12 +95,12 @@ describe('transfer-hook', () => { const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer, mint], { skipPreflight: true, - commitment: 'finalized', + commitment: "finalized", }); const txDetails = await program.provider.connection.getTransaction(txSig, { maxSupportedTransactionVersion: 0, - commitment: 'confirmed', + commitment: "confirmed", }); console.log(txDetails.meta.logMessages); @@ -99,7 +109,7 @@ describe('transfer-hook', () => { // Create the two token accounts for the transfer-hook enabled mint // Fund the sender token account with 100 tokens - it('Create Token Accounts and Mint Tokens', async () => { + it("Create Token Accounts and Mint Tokens", async () => { // 100 tokens const amount = 100 * 10 ** decimals; @@ -129,7 +139,7 @@ describe('transfer-hook', () => { }); // Account to store extra accounts required by the transfer hook instruction - it('Create ExtraAccountMetaList Account', async () => { + it("Create ExtraAccountMetaList Account", async () => { const initializeExtraAccountMetaListInstruction = await program.methods .initializeExtraAccountMetaList() .accounts({ @@ -139,11 +149,14 @@ describe('transfer-hook', () => { const transaction = new Transaction().add(initializeExtraAccountMetaListInstruction); - const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { skipPreflight: true, commitment: 'confirmed' }); - console.log('Transaction Signature:', txSig); + const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { + skipPreflight: true, + commitment: "confirmed", + }); + console.log("Transaction Signature:", txSig); }); - it('Transfer Hook with Extra Account Meta', async () => { + it("Transfer Hook with Extra Account Meta", async () => { // 1 tokens const amount = 1 * 10 ** decimals; const amountBigInt = BigInt(amount); @@ -157,7 +170,7 @@ describe('transfer-hook', () => { amountBigInt, decimals, [], - 'confirmed', + "confirmed", TOKEN_2022_PROGRAM_ID, ); @@ -168,10 +181,10 @@ describe('transfer-hook', () => { const transaction = new Transaction().add(transferInstructionWithHelper); const txSig = await sendAndConfirmTransaction(connection, transaction, [wallet.payer], { skipPreflight: true }); - console.log('Transfer Signature:', txSig); + console.log("Transfer Signature:", txSig); }); - it('Try call transfer hook without transfer', async () => { + it("Try call transfer hook without transfer", async () => { const transferHookIx = await program.methods .transferHook(new BN(1)) .accounts({ diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/.prettierrc b/tokens/token-2022/transfer-hook/allow-block-list-token/.prettierrc deleted file mode 100644 index d6c3437b9..000000000 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "arrowParens": "always", - "printWidth": 120, - "semi": false, - "singleQuote": true, - "trailingComma": "all" -} diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/Anchor.toml b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/Anchor.toml index f449ee744..d517c1a46 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/Anchor.toml +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/Anchor.toml @@ -16,4 +16,4 @@ cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "../node_modules/.bin/jest --preset ts-jest" +test = "cargo test" diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/Cargo.toml b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/Cargo.toml index 60684ee07..f6d424dbe 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/Cargo.toml +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/Cargo.toml @@ -21,10 +21,9 @@ custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release # interface-instructions feature removed in Anchor 1.0 -anchor-lang = "1.0.0-rc.5" -anchor-spl = { version = "1.0.0-rc.5", features = [ +anchor-lang = "1.0.0" +anchor-spl = { version = "1.0.0", features = [ "token_2022_extensions", "token_2022", ] } @@ -34,6 +33,11 @@ spl-transfer-hook-interface = { version = "2.1.0" } spl-discriminator = "0.5.1" [dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/src/lib.rs b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/src/lib.rs index b3c370483..f8643aa66 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/src/lib.rs +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/src/lib.rs @@ -13,7 +13,7 @@ pub use instructions::*; pub use state::*; pub use utils::*; -declare_id!("3ku1ZEGvBEEfhaYsAzBZuecTPEa58ZRhoVqHVGpGxVGi"); +declare_id!("9kSUqBeRgchrr9HpGneGHxqZ19qLTYzRyYYm2qQgtDmU"); #[program] pub mod abl_token { diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/tests/test_abl_token.rs b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/tests/test_abl_token.rs new file mode 100644 index 000000000..286d30604 --- /dev/null +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/programs/abl-token/tests/test_abl_token.rs @@ -0,0 +1,86 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::Instruction, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::TOKEN_EXTENSIONS_PROGRAM_ID, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = abl_token::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/abl_token.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_init_config_and_init_mint() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + + // Derive PDAs + let (config_pda, _) = + Pubkey::find_program_address(&[b"config"], &program_id); + let (extra_account_meta_list, _) = Pubkey::find_program_address( + &[b"extra-account-metas", mint_keypair.pubkey().as_ref()], + &program_id, + ); + + // Step 1: Initialize config + let init_config_ix = Instruction::new_with_bytes( + program_id, + &abl_token::instruction::InitConfig {}.data(), + abl_token::accounts::InitConfig { + payer: payer.pubkey(), + config: config_pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_config_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 2: Initialize mint with transfer hook and metadata + let init_mint_args = abl_token::instructions::InitMintArgs { + name: "Test Token".to_string(), + symbol: "TEST".to_string(), + uri: "https://test.com".to_string(), + decimals: 6, + mint_authority: payer.pubkey(), + freeze_authority: payer.pubkey(), + permanent_delegate: payer.pubkey(), + transfer_hook_authority: payer.pubkey(), + mode: abl_token::Mode::Allow, + threshold: 0, + }; + let init_mint_ix = Instruction::new_with_bytes( + program_id, + &abl_token::instruction::InitMint { + args: init_mint_args, + } + .data(), + abl_token::accounts::InitMint { + payer: payer.pubkey(), + mint: mint_keypair.pubkey(), + extra_metas_account: extra_account_meta_list, + system_program: system_program::id(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_mint_ix], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); +} diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/src/abl-token-exports.ts b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/src/abl-token-exports.ts index 6d4b27af6..9e147ff51 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/src/abl-token-exports.ts +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/src/abl-token-exports.ts @@ -1,8 +1,8 @@ // Here we export some useful types and functions for interacting with the Anchor program. -import { AnchorProvider, Program } from '@anchor-lang/core'; -import { Cluster, PublicKey } from '@solana/web3.js'; -import ABLTokenIDL from '../target/idl/abl_token.json'; -import type { AblToken } from '../target/types/abl_token'; +import { type AnchorProvider, Program } from "@anchor-lang/core"; +import { type Cluster, PublicKey } from "@solana/web3.js"; +import ABLTokenIDL from "../target/idl/abl_token.json"; +import type { AblToken } from "../target/types/abl_token"; // Re-export the generated IDL and type export { ABLTokenIDL }; @@ -12,16 +12,22 @@ export const ABL_TOKEN_PROGRAM_ID = new PublicKey(ABLTokenIDL.address); // This is a helper function to get the Basic Anchor program. export function getABLTokenProgram(provider: AnchorProvider, address?: PublicKey): Program { - return new Program({ ...ABLTokenIDL, address: address ? address.toBase58() : ABLTokenIDL.address } as AblToken, provider); + return new Program( + { + ...ABLTokenIDL, + address: address ? address.toBase58() : ABLTokenIDL.address, + } as AblToken, + provider, + ); } // This is a helper function to get the program ID for the Basic program depending on the cluster. export function getABLTokenProgramId(cluster: Cluster) { switch (cluster) { - case 'devnet': - case 'testnet': + case "devnet": + case "testnet": // This is the program ID for the Basic program on devnet and testnet. - return new PublicKey('6z68wfurCMYkZG51s1Et9BJEd9nJGUusjHXNt4dGbNNF'); + return new PublicKey("6z68wfurCMYkZG51s1Et9BJEd9nJGUusjHXNt4dGbNNF"); default: return ABL_TOKEN_PROGRAM_ID; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/src/index.ts b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/src/index.ts index 04fdd85fb..d7552798e 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/src/index.ts +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/src/index.ts @@ -1 +1 @@ -export * from './abl-token-exports'; +export * from "./abl-token-exports"; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/tests/basic.test.ts b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/tests/basic.test.ts index c024a5251..b4c288f90 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/tests/basic.test.ts +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/anchor/tests/basic.test.ts @@ -1,14 +1,14 @@ -import * as anchor from '@anchor-lang/core'; -import { Program } from '@anchor-lang/core'; -import { AblToken } from '../target/types/abl_token'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import type { AblToken } from "../target/types/abl_token"; -describe('abl-token', () => { +describe("abl-token", () => { // Configure the client to use the local cluster. anchor.setProvider(anchor.AnchorProvider.env()); const _program = anchor.workspace.ABLToken as Program; - it('should run the program', async () => { + it("should run the program", async () => { // Add your test here. }); }); diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/eslint.config.mjs b/tokens/token-2022/transfer-hook/allow-block-list-token/eslint.config.mjs index 835e40116..6bcf64707 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/eslint.config.mjs +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/eslint.config.mjs @@ -1,6 +1,6 @@ -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { FlatCompat } from '@eslint/eslintrc'; +import { dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import { FlatCompat } from "@eslint/eslintrc"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -9,6 +9,6 @@ const compat = new FlatCompat({ baseDirectory: __dirname, }); -const eslintConfig = [...compat.extends('next/core-web-vitals', 'next/typescript')]; +const eslintConfig = [...compat.extends("next/core-web-vitals", "next/typescript")]; export default eslintConfig; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/next.config.ts b/tokens/token-2022/transfer-hook/allow-block-list-token/next.config.ts index 5e891cf00..e9ffa3083 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/next.config.ts +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/next.config.ts @@ -1,4 +1,4 @@ -import type { NextConfig } from 'next'; +import type { NextConfig } from "next"; const nextConfig: NextConfig = { /* config options here */ diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/package.json b/tokens/token-2022/transfer-hook/allow-block-list-token/package.json index e6885b10e..0ee93b631 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/package.json +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/package.json @@ -1,58 +1,58 @@ { - "name": "legacy-next-tailwind-basic", - "version": "0.0.0", - "private": true, - "scripts": { - "anchor": "cd anchor && anchor", - "anchor-build": "cd anchor && anchor build", - "anchor-localnet": "cd anchor && anchor localnet", - "anchor-test": "cd anchor && anchor test", - "build": "next build", - "ci": "npm run build && npm run lint && npm run format:check", - "dev": "next dev --turbopack", - "format": "prettier --write .", - "format:check": "prettier --check .", - "lint": "next lint", - "start": "next start" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@radix-ui/react-dialog": "^1.1.14", - "@radix-ui/react-dropdown-menu": "^2.1.15", - "@radix-ui/react-label": "^2.1.7", - "@radix-ui/react-slot": "^1.2.3", - "@solana/spl-token": "0.4.13", - "@solana/wallet-adapter-base": "0.9.27", - "@solana/wallet-adapter-react": "0.15.39", - "@solana/wallet-adapter-react-ui": "0.9.39", - "@solana/web3.js": "^1.98.4", - "@tanstack/react-query": "^5.82.0", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "jotai": "^2.12.5", - "lucide-react": "^0.525.0", - "next": "15.3.5", - "next-themes": "^0.4.6", - "react": "^19.1.0", - "react-dom": "^19.1.0", - "sonner": "^2.0.6", - "tailwind-merge": "^3.3.1", - "tw-animate-css": "^1.3.5" - }, - "devDependencies": { - "@eslint/eslintrc": "^3.3.1", - "@tailwindcss/postcss": "^4.1.4", - "@types/bn.js": "^5.1.6", - "@types/jest": "^29.5.14", - "@types/node": "^22.15.3", - "@types/react": "^19.1.2", - "@types/react-dom": "^19.1.2", - "eslint": "^9.25.1", - "eslint-config-next": "15.3.1", - "jest": "^29.7.0", - "prettier": "^3.5.3", - "tailwindcss": "^4.1.4", - "ts-jest": "^29.3.2", - "typescript": "^5.8.3" - } + "name": "legacy-next-tailwind-basic", + "version": "0.0.0", + "private": true, + "scripts": { + "anchor": "cd anchor && anchor", + "anchor-build": "cd anchor && anchor build", + "anchor-localnet": "cd anchor && anchor localnet", + "anchor-test": "cd anchor && anchor test", + "build": "next build", + "ci": "npm run build && npm run lint && npm run format:check", + "dev": "next dev --turbopack", + "format": "prettier --write .", + "format:check": "prettier --check .", + "lint": "next lint", + "start": "next start" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-slot": "^1.2.3", + "@solana/spl-token": "0.4.13", + "@solana/wallet-adapter-base": "0.9.27", + "@solana/wallet-adapter-react": "0.15.39", + "@solana/wallet-adapter-react-ui": "0.9.39", + "@solana/web3.js": "^1.98.4", + "@tanstack/react-query": "^5.82.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "jotai": "^2.12.5", + "lucide-react": "^0.525.0", + "next": "15.3.5", + "next-themes": "^0.4.6", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "sonner": "^2.0.6", + "tailwind-merge": "^3.3.1", + "tw-animate-css": "^1.3.5" + }, + "devDependencies": { + "@eslint/eslintrc": "^3.3.1", + "@tailwindcss/postcss": "^4.1.4", + "@types/bn.js": "^5.1.6", + "@types/jest": "^29.5.14", + "@types/node": "^22.15.3", + "@types/react": "^19.1.2", + "@types/react-dom": "^19.1.2", + "eslint": "^9.25.1", + "eslint-config-next": "15.3.1", + "jest": "^29.7.0", + "prettier": "^3.5.3", + "tailwindcss": "^4.1.4", + "ts-jest": "^29.3.2", + "typescript": "^5.8.3" + } } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/pnpm-lock.yaml b/tokens/token-2022/transfer-hook/allow-block-list-token/pnpm-lock.yaml index 86e88fcf3..669a20099 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/pnpm-lock.yaml +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@radix-ui/react-dialog': specifier: ^1.1.14 version: 1.1.15(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -124,18 +124,18 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/code-frame@7.27.1': @@ -4226,16 +4226,16 @@ snapshots: '@alloc/quick-lru@5.2.0': {} - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -4253,7 +4253,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/code-frame@7.27.1': dependencies: diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/postcss.config.mjs b/tokens/token-2022/transfer-hook/allow-block-list-token/postcss.config.mjs index ba720fe55..c7bcb4b1e 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/postcss.config.mjs +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/postcss.config.mjs @@ -1,5 +1,5 @@ const config = { - plugins: ['@tailwindcss/postcss'], + plugins: ["@tailwindcss/postcss"], }; export default config; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/account/[address]/page.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/account/[address]/page.tsx index 5bb6688e9..0f46f881f 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/account/[address]/page.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/account/[address]/page.tsx @@ -1,5 +1,5 @@ -import AccountDetailFeature from '@/components/account/account-detail-feature' +import AccountDetailFeature from "@/components/account/account-detail-feature"; export default function Page() { - return + return ; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/account/page.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/account/page.tsx index 1b0e27684..cf7d07d31 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/account/page.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/account/page.tsx @@ -1,5 +1,5 @@ -import AccountListFeature from '@/components/account/account-list-feature' +import AccountListFeature from "@/components/account/account-list-feature"; export default function Page() { - return + return ; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/config/page.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/config/page.tsx index e1cde08f1..15749c63c 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/config/page.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/config/page.tsx @@ -1,6 +1,5 @@ - -import AblTokenConfig from '@/components/abl-token/abl-token-config' +import AblTokenConfig from "@/components/abl-token/abl-token-config"; export default function Page() { - return + return ; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/create-token/page.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/create-token/page.tsx index 39c705292..93a0c913e 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/create-token/page.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/create-token/page.tsx @@ -1,5 +1,5 @@ -import AblTokenFeature from '@/components/abl-token/abl-token-feature' +import AblTokenFeature from "@/components/abl-token/abl-token-feature"; export default function Page() { - return + return ; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/globals.css b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/globals.css index 2edb31d83..00bfb4477 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/globals.css +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/globals.css @@ -1,5 +1,5 @@ -@import 'tailwindcss'; -@import 'tw-animate-css'; +@import "tailwindcss"; +@import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -121,7 +121,7 @@ } .wallet-adapter-button-trigger { - height: auto !important; + height: auto; @apply !border !bg-background !shadow-xs hover:!bg-accent !text-accent-foreground hover:!text-accent-foreground dark:!bg-input/30 !border-input/10 dark:!border-input dark:hover:!bg-input/50; @apply !px-2 !py-[6px] !rounded-md !text-sm !font-semibold !shadow-sm !transition-all; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/layout.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/layout.tsx index 6cfdc1d13..7cc19d2be 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/layout.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/layout.tsx @@ -1,22 +1,22 @@ -import type { Metadata } from 'next' -import './globals.css' -import { AppProviders } from '@/components/app-providers' -import { AppLayout } from '@/components/app-layout' -import React from 'react' +import type { Metadata } from "next"; +import "./globals.css"; +import type React from "react"; +import { AppLayout } from "@/components/app-layout"; +import { AppProviders } from "@/components/app-providers"; export const metadata: Metadata = { - title: 'ABL Token', - description: 'ABL Token', -} + title: "ABL Token", + description: "ABL Token", +}; const links: { label: string; path: string }[] = [ // More links... - { label: 'Home', path: '/' }, - { label: 'Account', path: '/account' }, - { label: 'Config', path: '/config' }, - { label: 'Create New Token', path: '/create-token' }, - { label: 'Manage Token', path: '/manage-token' }, -] + { label: "Home", path: "/" }, + { label: "Account", path: "/account" }, + { label: "Config", path: "/config" }, + { label: "Create New Token", path: "/create-token" }, + { label: "Manage Token", path: "/manage-token" }, +]; export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { return ( @@ -27,15 +27,15 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac - ) + ); } // Patch BigInt so we can log it using JSON.stringify without any errors declare global { interface BigInt { - toJSON(): string + toJSON(): string; } } BigInt.prototype.toJSON = function () { - return this.toString() -} + return this.toString(); +}; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/manage-token/[address]/page.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/manage-token/[address]/page.tsx index 7a5c53e12..b7cd18e03 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/manage-token/[address]/page.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/manage-token/[address]/page.tsx @@ -1,5 +1,5 @@ -import AblTokenManageTokenDetail from '@/components/abl-token/abl-token-manage-token-detail' +import AblTokenManageTokenDetail from "@/components/abl-token/abl-token-manage-token-detail"; export default function Page() { - return + return ; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/manage-token/page.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/manage-token/page.tsx index 175476840..8c33d78e8 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/manage-token/page.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/manage-token/page.tsx @@ -1,5 +1,5 @@ -import AblTokenManageToken from '@/components/abl-token/abl-token-manage-token' +import AblTokenManageToken from "@/components/abl-token/abl-token-manage-token"; export default function Page() { - return + return ; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/page.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/page.tsx index b0e9cd11b..a7d176adc 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/page.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/app/page.tsx @@ -1,5 +1,5 @@ -import { DashboardFeature } from '@/components/dashboard/dashboard-feature' +import { DashboardFeature } from "@/components/dashboard/dashboard-feature"; export default function Home() { - return + return ; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-config.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-config.tsx index 57a42b9fd..6cfd261e2 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-config.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-config.tsx @@ -1,18 +1,18 @@ -'use client' +"use client"; -import { useWallet } from '@solana/wallet-adapter-react' -import { ExplorerLink } from '../cluster/cluster-ui' -import { WalletButton } from '../solana/solana-provider' -import { useAblTokenProgram } from './abl-token-data-access' -import { AppHero } from '../app-hero' -import { ellipsify } from '@/lib/utils' -import { Button } from '@/components/ui/button' -import React from 'react' -import { PublicKey } from '@solana/web3.js' +import { useWallet } from "@solana/wallet-adapter-react"; +import { PublicKey } from "@solana/web3.js"; +import React from "react"; +import { Button } from "@/components/ui/button"; +import { ellipsify } from "@/lib/utils"; +import { AppHero } from "../app-hero"; +import { ExplorerLink } from "../cluster/cluster-ui"; +import { WalletButton } from "../solana/solana-provider"; +import { useAblTokenProgram } from "./abl-token-data-access"; export default function AblTokenConfig() { - const { publicKey } = useWallet() - const { programId, getConfig, getAbWallets } = useAblTokenProgram() + const { publicKey } = useWallet(); + const { programId, getConfig, getAbWallets } = useAblTokenProgram(); const config = getConfig.data; let abWallets = getAbWallets.data; @@ -20,11 +20,11 @@ export default function AblTokenConfig() { const handleWalletListUpdate = React.useCallback(async () => { await getAbWallets.refetch(); abWallets = getAbWallets.data; - }, []) + }, [getAbWallets.refetch, getAbWallets.data]); return publicKey ? (
- +

@@ -56,13 +56,12 @@ export default function AblTokenConfig() {
- ) + ); } - export function AblTokenConfigCreate() { - const { initConfig, getConfig } = useAblTokenProgram() - const { publicKey } = useWallet() + const { initConfig, getConfig } = useAblTokenProgram(); + const { publicKey } = useWallet(); const handleCreate = async () => { if (!publicKey) return; @@ -71,7 +70,7 @@ export function AblTokenConfigCreate() { // Refresh the config list getConfig.refetch(); } catch (err) { - console.error('Failed to create config:', err); + console.error("Failed to create config:", err); } }; @@ -81,17 +80,23 @@ export function AblTokenConfigCreate() {

Initialize the ABL Token configuration. This will set up the necessary accounts for managing allow/block lists.

- ); } -export function AblTokenConfigList({ abWallets }: { abWallets: {publicKey: PublicKey, account: {wallet: PublicKey, allowed: boolean}}[] | undefined }) { +export function AblTokenConfigList({ + abWallets, +}: { + abWallets: + | { + publicKey: PublicKey; + account: { wallet: PublicKey; allowed: boolean }; + }[] + | undefined; +}) { return (

ABL Token Config List

@@ -109,8 +114,8 @@ export function AblTokenConfigList({ abWallets }: { abWallets: {publicKey: Publi {wallet.account.wallet.toString()} - - {wallet.account.allowed ? 'Allowed' : 'Blocked'} + + {wallet.account.allowed ? "Allowed" : "Blocked"} @@ -127,139 +132,139 @@ export function AblTokenConfigList({ abWallets }: { abWallets: {publicKey: Publi interface WalletChange { address: string; - mode: 'allow' | 'block' | 'remove'; - status?: 'pending' | 'success' | 'error'; + mode: "allow" | "block" | "remove"; + status?: "pending" | "success" | "error"; error?: string; } export function AblTokenConfigListChange({ onWalletListUpdate }: { onWalletListUpdate: () => void }) { - const { getAbWallets, processBatchWallets } = useAblTokenProgram() - const [isEditing, setIsEditing] = React.useState(false) - const [walletChanges, setWalletChanges] = React.useState([]) - const [isProcessing, setIsProcessing] = React.useState(false) + const { getAbWallets, processBatchWallets } = useAblTokenProgram(); + const [isEditing, setIsEditing] = React.useState(false); + const [walletChanges, setWalletChanges] = React.useState([]); + const [isProcessing, setIsProcessing] = React.useState(false); const existingWallets = React.useMemo(() => { - const wallets = getAbWallets.data || [] - return new Map(wallets.map(w => [w.account.wallet.toString(), w.account.allowed])) - }, [getAbWallets.data]) + const wallets = getAbWallets.data || []; + return new Map(wallets.map((w) => [w.account.wallet.toString(), w.account.allowed])); + }, [getAbWallets.data]); const handleDragOver = (e: React.DragEvent) => { - e.preventDefault() - } + e.preventDefault(); + }; const handleDrop = async (e: React.DragEvent) => { - e.preventDefault() - const file = e.dataTransfer.files[0] - if (file && file.type === 'text/csv') { - const text = await file.text() - const rows = text.split('\n') - + e.preventDefault(); + const file = e.dataTransfer.files[0]; + if (file && file.type === "text/csv") { + const text = await file.text(); + const rows = text.split("\n"); + // Create a Set of existing wallet addresses for deduplication const existingAddresses = new Set([ ...Array.from(existingWallets.keys()), - ...walletChanges.map(w => w.address) - ]) - + ...walletChanges.map((w) => w.address), + ]); + const parsed: WalletChange[] = rows - .filter(row => row.trim()) - .map(row => { - const [address, mode] = row.split(',').map(field => field.trim()) + .filter((row) => row.trim()) + .map((row) => { + const [address, mode] = row.split(",").map((field) => field.trim()); return { address, - mode: mode.toLowerCase() as 'allow' | 'block' | 'remove' - } + mode: mode.toLowerCase() as "allow" | "block" | "remove", + }; }) - .filter(entry => { + .filter((entry) => { try { - new PublicKey(entry.address) - return ['allow', 'block', 'remove'].includes(entry.mode) + new PublicKey(entry.address); + return ["allow", "block", "remove"].includes(entry.mode); } catch { - return false + return false; } }) - .filter(entry => { + .filter((entry) => { // Only allow 'remove' for existing wallets - if (entry.mode === 'remove') { - return existingWallets.has(entry.address) + if (entry.mode === "remove") { + return existingWallets.has(entry.address); } - return true + return true; }) // Deduplicate entries, keeping the last occurrence of each address .reduce((acc, entry) => { - const existingIndex = acc.findIndex(w => w.address === entry.address) + const existingIndex = acc.findIndex((w) => w.address === entry.address); if (existingIndex >= 0) { - acc[existingIndex] = entry + acc[existingIndex] = entry; } else { - acc.push(entry) + acc.push(entry); } - return acc + return acc; }, [] as WalletChange[]) // Filter out entries that already exist in the current state - .filter(entry => !existingAddresses.has(entry.address)) + .filter((entry) => !existingAddresses.has(entry.address)); if (parsed.length > 0) { - setWalletChanges(prev => [...prev, ...parsed]) - setIsEditing(true) + setWalletChanges((prev) => [...prev, ...parsed]); + setIsEditing(true); } } - } + }; const handleAddWallet = () => { - setWalletChanges(prev => [...prev, { address: '', mode: 'allow' }]) - setIsEditing(true) - } + setWalletChanges((prev) => [...prev, { address: "", mode: "allow" }]); + setIsEditing(true); + }; const handleUpdateWallet = (index: number, field: keyof WalletChange, value: string) => { - setWalletChanges(prev => prev.map((wallet, i) => - i === index ? { ...wallet, [field]: value } : wallet - )) - } + setWalletChanges((prev) => prev.map((wallet, i) => (i === index ? { ...wallet, [field]: value } : wallet))); + }; const handleRemoveWallet = (index: number) => { - setWalletChanges(prev => prev.filter((_, i) => i !== index)) - } + setWalletChanges((prev) => prev.filter((_, i) => i !== index)); + }; const processWallets = async () => { - setIsProcessing(true) - const batchSize = 10 - const batches = [] - + setIsProcessing(true); + const batchSize = 10; + const batches = []; + for (let i = 0; i < walletChanges.length; i += batchSize) { - batches.push(walletChanges.slice(i, i + batchSize)) + batches.push(walletChanges.slice(i, i + batchSize)); } for (const batch of batches) { try { await processBatchWallets.mutateAsync({ - wallets: batch.map(w => ({ + wallets: batch.map((w) => ({ wallet: new PublicKey(w.address), - mode: w.mode - })) - }) - + mode: w.mode, + })), + }); + // Mark batch as successful - setWalletChanges(prev => prev.map(wallet => - batch.some(b => b.address === wallet.address) - ? { ...wallet, status: 'success' } - : wallet - )) + setWalletChanges((prev) => + prev.map((wallet) => + batch.some((b) => b.address === wallet.address) ? { ...wallet, status: "success" } : wallet, + ), + ); } catch (error: unknown) { - const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred' + const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; // Mark batch as failed - setWalletChanges(prev => prev.map(wallet => - batch.some(b => b.address === wallet.address) - ? { ...wallet, status: 'error', error: errorMessage } - : wallet - )) + setWalletChanges((prev) => + prev.map((wallet) => + batch.some((b) => b.address === wallet.address) + ? { ...wallet, status: "error", error: errorMessage } + : wallet, + ), + ); } } // Refresh wallet list and clear successful changes - await getAbWallets.refetch() - setWalletChanges(prev => prev.filter(w => w.status !== 'success')) - setIsProcessing(false) + await getAbWallets.refetch(); + setWalletChanges((prev) => prev.filter((w) => w.status !== "success")); + setIsProcessing(false); // Notify parent component to update the wallet list - onWalletListUpdate() - } + onWalletListUpdate(); + }; return (
@@ -270,17 +275,15 @@ export function AblTokenConfigListChange({ onWalletListUpdate }: { onWalletListU Add Wallet {isEditing && ( - )}
-
Mode can be: allow, block, or remove (remove only works for existing wallets)

-
+ {walletChanges.length > 0 && (
@@ -304,13 +307,13 @@ export function AblTokenConfigListChange({ onWalletListUpdate }: { onWalletListU {walletChanges.map((wallet, index) => ( - + handleUpdateWallet(index, 'address', e.target.value)} + onChange={(e) => handleUpdateWallet(index, "address", e.target.value)} placeholder="Wallet address" disabled={isProcessing} /> @@ -319,30 +322,26 @@ export function AblTokenConfigListChange({ onWalletListUpdate }: { onWalletListU - {wallet.status === 'success' && ( - - )} - {wallet.status === 'error' && ( - + {wallet.status === "success" && } + {wallet.status === "error" && ( + + ✗ + )} - @@ -353,5 +352,5 @@ export function AblTokenConfigListChange({ onWalletListUpdate }: { onWalletListU
)} - ) -} \ No newline at end of file + ); +} diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-data-access.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-data-access.tsx index 3b1194a3e..505550dac 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-data-access.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-data-access.tsx @@ -1,290 +1,281 @@ -'use client' - -import { getABLTokenProgram, getABLTokenProgramId } from '@project/anchor' -import { useConnection } from '@solana/wallet-adapter-react' -import { Cluster, Keypair, PublicKey, Transaction } from '@solana/web3.js' -import { useMutation, useQuery } from '@tanstack/react-query' -import { useMemo } from 'react' -import { useCluster } from '../cluster/cluster-data-access' -import { useAnchorProvider } from '../solana/solana-provider' -import { useTransactionToast } from '../use-transaction-toast' -import { toast } from 'sonner' -import { BN } from '@anchor-lang/core' -import { createAssociatedTokenAccountIdempotentInstruction, createMintToCheckedInstruction, getAssociatedTokenAddressSync, getMint, getPermanentDelegate, getTokenMetadata, getTransferHook, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token' +"use client"; + +import type { BN } from "@anchor-lang/core"; +import { getABLTokenProgram, getABLTokenProgramId } from "@project/anchor"; +import { + createAssociatedTokenAccountIdempotentInstruction, + createMintToCheckedInstruction, + getAssociatedTokenAddressSync, + getMint, + getPermanentDelegate, + getTokenMetadata, + getTransferHook, + TOKEN_2022_PROGRAM_ID, +} from "@solana/spl-token"; +import { useConnection } from "@solana/wallet-adapter-react"; +import { type Cluster, Keypair, PublicKey, Transaction } from "@solana/web3.js"; +import { useMutation, useQuery } from "@tanstack/react-query"; +import { useMemo } from "react"; +import { toast } from "sonner"; +import { useCluster } from "../cluster/cluster-data-access"; +import { useAnchorProvider } from "../solana/solana-provider"; +import { useTransactionToast } from "../use-transaction-toast"; export function useHasTransferHookEnabled(mint: PublicKey) { - const { connection } = useConnection() - const { cluster } = useCluster() - const programId = useMemo(() => getABLTokenProgramId(cluster.network as Cluster), [cluster]) + const { connection } = useConnection(); + const { cluster } = useCluster(); + const programId = useMemo(() => getABLTokenProgramId(cluster.network as Cluster), [cluster]); return useQuery({ - queryKey: ['has-transfer-hook', { cluster }], + queryKey: ["has-transfer-hook", { cluster }], queryFn: async () => { - const mintInfo = await getMint( - connection, - mint, - "confirmed", - TOKEN_2022_PROGRAM_ID, - ); + const mintInfo = await getMint(connection, mint, "confirmed", TOKEN_2022_PROGRAM_ID); const transferHook = getTransferHook(mintInfo); return transferHook !== null && programId.equals(transferHook.programId); }, - }) + }); } export function useGetToken(mint: PublicKey) { - const { connection } = useConnection() - const { cluster } = useCluster() - const programId = useMemo(() => getABLTokenProgramId(cluster.network as Cluster), [cluster]) + const { connection } = useConnection(); + const { cluster } = useCluster(); + const programId = useMemo(() => getABLTokenProgramId(cluster.network as Cluster), [cluster]); return useQuery({ - queryKey: ['get-token', { endpoint: connection.rpcEndpoint, mint }], - queryFn: async () => { - const mintInfo = await getMint( - connection, - mint, - "confirmed", - TOKEN_2022_PROGRAM_ID, - ); - - const metadata = await getTokenMetadata( - connection, - mint, - "confirmed", - TOKEN_2022_PROGRAM_ID, - ); + queryKey: ["get-token", { endpoint: connection.rpcEndpoint, mint }], + queryFn: async () => { + const mintInfo = await getMint(connection, mint, "confirmed", TOKEN_2022_PROGRAM_ID); - const mode = metadata?.additionalMetadata.find((metadata) => metadata[0] === "AB")?.[1] || null; - const threshold = metadata?.additionalMetadata.find((metadata) => metadata[0] === "threshold")?.[1] || null; + const metadata = await getTokenMetadata(connection, mint, "confirmed", TOKEN_2022_PROGRAM_ID); - const permanentDelegate = await getPermanentDelegate(mintInfo); + const mode = metadata?.additionalMetadata.find((metadata) => metadata[0] === "AB")?.[1] || null; + const threshold = metadata?.additionalMetadata.find((metadata) => metadata[0] === "threshold")?.[1] || null; - const transferHook = getTransferHook(mintInfo); + const permanentDelegate = await getPermanentDelegate(mintInfo); - const isTransferHookEnabled = transferHook !== null; - const isTransferHookSet = transferHook?.programId?.equals(programId) || false; - const transferHookProgramId = transferHook?.programId || null; + const transferHook = getTransferHook(mintInfo); - return { - name: metadata?.name, - symbol: metadata?.symbol, - uri: metadata?.uri, - decimals: mintInfo.decimals, - supply: mintInfo.supply, - mintAuthority: mintInfo.mintAuthority, - freezeAuthority: mintInfo.freezeAuthority, - permanentDelegate: permanentDelegate?.delegate ?? null, - isTransferHookEnabled, - isTransferHookSet, - transferHookProgramId, - mode, - threshold, - } - }, -}) + const isTransferHookEnabled = transferHook !== null; + const isTransferHookSet = transferHook?.programId?.equals(programId) || false; + const transferHookProgramId = transferHook?.programId || null; + + return { + name: metadata?.name, + symbol: metadata?.symbol, + uri: metadata?.uri, + decimals: mintInfo.decimals, + supply: mintInfo.supply, + mintAuthority: mintInfo.mintAuthority, + freezeAuthority: mintInfo.freezeAuthority, + permanentDelegate: permanentDelegate?.delegate ?? null, + isTransferHookEnabled, + isTransferHookSet, + transferHookProgramId, + mode, + threshold, + }; + }, + }); } - export function useAblTokenProgram() { - const { connection } = useConnection() - const { cluster } = useCluster() - const transactionToast = useTransactionToast() - const provider = useAnchorProvider() - const programId = useMemo(() => getABLTokenProgramId(cluster.network as Cluster), [cluster]) - const program = useMemo(() => getABLTokenProgram(provider, programId), [provider, programId]) + const { connection } = useConnection(); + const { cluster } = useCluster(); + const transactionToast = useTransactionToast(); + const provider = useAnchorProvider(); + const programId = useMemo(() => getABLTokenProgramId(cluster.network as Cluster), [cluster]); + const program = useMemo(() => getABLTokenProgram(provider, programId), [provider, programId]); const getProgramAccount = useQuery({ - queryKey: ['get-program-account', { cluster }], + queryKey: ["get-program-account", { cluster }], queryFn: () => connection.getParsedAccountInfo(programId), - }) + }); const initToken = useMutation({ - mutationKey: ['abl-token', 'init-token', { cluster }], + mutationKey: ["abl-token", "init-token", { cluster }], mutationFn: (args: { - mintAuthority: PublicKey, - freezeAuthority: PublicKey, - permanentDelegate: PublicKey, - transferHookAuthority: PublicKey, - mode: string, - threshold: BN, - name: string, - symbol: string, - uri: string, - decimals: number, + mintAuthority: PublicKey; + freezeAuthority: PublicKey; + permanentDelegate: PublicKey; + transferHookAuthority: PublicKey; + mode: string; + threshold: BN; + name: string; + symbol: string; + uri: string; + decimals: number; }) => { - const modeEnum = args.mode === 'allow' ? { allow: {} } : args.mode === 'block' ? { block: {}} : { mixed: {}}; + const modeEnum = args.mode === "allow" ? { allow: {} } : args.mode === "block" ? { block: {} } : { mixed: {} }; const mint = Keypair.generate(); - return program.methods.initMint({ - decimals: args.decimals, - mintAuthority: args.mintAuthority, - freezeAuthority: args.freezeAuthority, - permanentDelegate: args.permanentDelegate, - transferHookAuthority: args.mintAuthority, - mode: modeEnum, - threshold: args.threshold, - name: args.name, - symbol: args.symbol, - uri: args.uri, - }).accounts({ - mint: mint.publicKey, - }).signers([mint]).rpc().then((signature) => ({ signature, mintAddress: mint.publicKey })) + return program.methods + .initMint({ + decimals: args.decimals, + mintAuthority: args.mintAuthority, + freezeAuthority: args.freezeAuthority, + permanentDelegate: args.permanentDelegate, + transferHookAuthority: args.mintAuthority, + mode: modeEnum, + threshold: args.threshold, + name: args.name, + symbol: args.symbol, + uri: args.uri, + }) + .accounts({ + mint: mint.publicKey, + }) + .signers([mint]) + .rpc() + .then((signature) => ({ signature, mintAddress: mint.publicKey })); }, onSuccess: ({ signature, mintAddress }) => { - transactionToast(signature) - window.location.href = `/manage-token/${mintAddress.toString()}` + transactionToast(signature); + window.location.href = `/manage-token/${mintAddress.toString()}`; }, - onError: () => toast.error('Failed to initialize token'), - }) + onError: () => toast.error("Failed to initialize token"), + }); const attachToExistingToken = useMutation({ - mutationKey: ['abl-token', 'attach-to-existing-token', { cluster }], - mutationFn: (args: { - mint: PublicKey, - }) => { - return program.methods.attachToMint().accounts({ - mint: args.mint, - }).rpc() + mutationKey: ["abl-token", "attach-to-existing-token", { cluster }], + mutationFn: (args: { mint: PublicKey }) => { + return program.methods + .attachToMint() + .accounts({ + mint: args.mint, + }) + .rpc(); }, onSuccess: (signature) => { - transactionToast(signature) + transactionToast(signature); }, - onError: () => toast.error('Failed to initialize token'), - }) + onError: () => toast.error("Failed to initialize token"), + }); const changeMode = useMutation({ - mutationKey: ['abl-token', 'change-mode', { cluster }], - mutationFn: (args: { - mode: string, - threshold: BN, - mint: PublicKey, - }) => { - const modeEnum = args.mode === 'Allow' ? { allow: {} } : args.mode === 'Block' ? { block: {}} : { mixed: {}} - return program.methods.changeMode({ - mode: modeEnum, - threshold: args.threshold, - }).accounts({ - mint: args.mint, - }).rpc() + mutationKey: ["abl-token", "change-mode", { cluster }], + mutationFn: (args: { mode: string; threshold: BN; mint: PublicKey }) => { + const modeEnum = args.mode === "Allow" ? { allow: {} } : args.mode === "Block" ? { block: {} } : { mixed: {} }; + return program.methods + .changeMode({ + mode: modeEnum, + threshold: args.threshold, + }) + .accounts({ + mint: args.mint, + }) + .rpc(); }, onSuccess: (signature) => { - transactionToast(signature) + transactionToast(signature); }, - onError: () => toast.error('Failed to run program'), - }) + onError: () => toast.error("Failed to run program"), + }); const initWallet = useMutation({ - mutationKey: ['abl-token', 'change-mode', { cluster }], - mutationFn: (args: { - wallet: PublicKey, - allowed: boolean, - }) => { - return program.methods.initWallet({ - allowed: args.allowed, - }).accounts({ - wallet: args.wallet, - }).rpc() + mutationKey: ["abl-token", "change-mode", { cluster }], + mutationFn: (args: { wallet: PublicKey; allowed: boolean }) => { + return program.methods + .initWallet({ + allowed: args.allowed, + }) + .accounts({ + wallet: args.wallet, + }) + .rpc(); }, onSuccess: (signature) => { - transactionToast(signature) + transactionToast(signature); }, - onError: () => toast.error('Failed to run program'), - }) + onError: () => toast.error("Failed to run program"), + }); const processBatchWallets = useMutation({ - mutationKey: ['abl-token', 'process-batch-wallets', { cluster }], - mutationFn: async (args: { - wallets: {wallet: PublicKey, mode: "allow" | "block" | "remove"}[], - }) => { - const instructions = await Promise.all(args.wallets.map((wallet) => { - if (wallet.mode === "remove") { - const [abWalletPda] = PublicKey.findProgramAddressSync( - [ - Buffer.from('ab_wallet'), - wallet.wallet.toBuffer(), - ], - program.programId - ); - return program.methods.removeWallet().accounts({ - abWallet: abWalletPda, - }).instruction() - } - return program.methods.initWallet({ - allowed: wallet.mode === "allow", - }).accounts({ - wallet: wallet.wallet, - }).instruction() - })); - + mutationKey: ["abl-token", "process-batch-wallets", { cluster }], + mutationFn: async (args: { wallets: { wallet: PublicKey; mode: "allow" | "block" | "remove" }[] }) => { + const instructions = await Promise.all( + args.wallets.map((wallet) => { + if (wallet.mode === "remove") { + const [abWalletPda] = PublicKey.findProgramAddressSync( + [Buffer.from("ab_wallet"), wallet.wallet.toBuffer()], + program.programId, + ); + return program.methods + .removeWallet() + .accounts({ + abWallet: abWalletPda, + }) + .instruction(); + } + return program.methods + .initWallet({ + allowed: wallet.mode === "allow", + }) + .accounts({ + wallet: wallet.wallet, + }) + .instruction(); + }), + ); + const transaction = new Transaction(); transaction.add(...instructions); transaction.feePayer = provider.wallet.publicKey; transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash; //transaction.sign(provider.wallet); - const signedTx = await provider.wallet.signTransaction(transaction); + const signedTx = await provider.wallet.signTransaction(transaction); return connection.sendRawTransaction(signedTx.serialize()); - }, onSuccess: (signature) => { - transactionToast(signature) + transactionToast(signature); }, - onError: () => toast.error('Failed to run program'), - }) - + onError: () => toast.error("Failed to run program"), + }); const removeWallet = useMutation({ - mutationKey: ['abl-token', 'change-mode', { cluster }], - mutationFn: (args: { - wallet: PublicKey, - }) => { + mutationKey: ["abl-token", "change-mode", { cluster }], + mutationFn: (args: { wallet: PublicKey }) => { const [abWalletPda] = PublicKey.findProgramAddressSync( - [ - Buffer.from('ab_wallet'), - args.wallet.toBuffer(), - ], - program.programId + [Buffer.from("ab_wallet"), args.wallet.toBuffer()], + program.programId, ); - return program.methods.removeWallet().accounts({ - abWallet: abWalletPda, - }).rpc() + return program.methods + .removeWallet() + .accounts({ + abWallet: abWalletPda, + }) + .rpc(); }, onSuccess: (signature) => { - transactionToast(signature) + transactionToast(signature); }, - onError: () => toast.error('Failed to run program'), - }) - + onError: () => toast.error("Failed to run program"), + }); const initConfig = useMutation({ - mutationKey: ['abl-token', 'init-config', { cluster }], + mutationKey: ["abl-token", "init-config", { cluster }], mutationFn: () => { - return program.methods.initConfig().rpc() + return program.methods.initConfig().rpc(); }, - }) + }); const getConfig = useQuery({ - queryKey: ['get-config', { cluster }], + queryKey: ["get-config", { cluster }], queryFn: () => { - const [configPda] = PublicKey.findProgramAddressSync( - [Buffer.from('config')], - program.programId - ); - return program.account.config.fetch(configPda) + const [configPda] = PublicKey.findProgramAddressSync([Buffer.from("config")], program.programId); + return program.account.config.fetch(configPda); }, - }) - + }); + const getAbWallets = useQuery({ - queryKey: ['get-ab-wallets', { cluster }], + queryKey: ["get-ab-wallets", { cluster }], queryFn: () => { - return program.account.abWallet.all() + return program.account.abWallet.all(); }, - }) - + }); - -/* + /* const getBalance = useQuery({ queryKey: ['get-balance', { cluster }], queryFn: () => { @@ -293,35 +284,39 @@ export function useAblTokenProgram() { })*/ const mintTo = useMutation({ - mutationKey: ['abl-token', 'mint-to', { cluster }], - mutationFn: async (args: { - mint: PublicKey, - amount: BN, - recipient: PublicKey, - }) => { - const mintInfo = await getMint( - connection, + mutationKey: ["abl-token", "mint-to", { cluster }], + mutationFn: async (args: { mint: PublicKey; amount: BN; recipient: PublicKey }) => { + const mintInfo = await getMint(connection, args.mint, "confirmed", TOKEN_2022_PROGRAM_ID); + const ata = getAssociatedTokenAddressSync(args.mint, args.recipient, true, TOKEN_2022_PROGRAM_ID); + + const ix = createAssociatedTokenAccountIdempotentInstruction( + provider.publicKey, + ata, + args.recipient, args.mint, - "confirmed", TOKEN_2022_PROGRAM_ID, ); - const ata = getAssociatedTokenAddressSync(args.mint, args.recipient, true, TOKEN_2022_PROGRAM_ID); - - const ix = createAssociatedTokenAccountIdempotentInstruction(provider.publicKey, ata, args.recipient, args.mint, TOKEN_2022_PROGRAM_ID); - const ix2 = createMintToCheckedInstruction(args.mint, ata, provider.publicKey, args.amount.toNumber(), mintInfo.decimals, undefined, TOKEN_2022_PROGRAM_ID); + const ix2 = createMintToCheckedInstruction( + args.mint, + ata, + provider.publicKey, + args.amount.toNumber(), + mintInfo.decimals, + undefined, + TOKEN_2022_PROGRAM_ID, + ); const tx = new Transaction(); tx.add(ix, ix2); tx.feePayer = provider.wallet.publicKey; tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash; - const signedTx = await provider.wallet.signTransaction(tx); - return connection.sendRawTransaction(signedTx.serialize()) + const signedTx = await provider.wallet.signTransaction(tx); + return connection.sendRawTransaction(signedTx.serialize()); }, onSuccess: (signature) => { - transactionToast(signature) + transactionToast(signature); }, - onError: () => toast.error('Failed to run program'), - }) - + onError: () => toast.error("Failed to run program"), + }); return { program, @@ -337,6 +332,5 @@ export function useAblTokenProgram() { processBatchWallets, mintTo, attachToExistingToken, - } + }; } - diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-feature.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-feature.tsx index f49c2f906..201a66a28 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-feature.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-feature.tsx @@ -1,16 +1,16 @@ -'use client' +"use client"; -import { useWallet } from '@solana/wallet-adapter-react' -import { ExplorerLink } from '../cluster/cluster-ui' -import { WalletButton } from '../solana/solana-provider' -import { useAblTokenProgram } from './abl-token-data-access' -import { AblTokenCreate, AblTokenProgram } from './abl-token-ui' -import { AppHero } from '../app-hero' -import { ellipsify } from '@/lib/utils' +import { useWallet } from "@solana/wallet-adapter-react"; +import { ellipsify } from "@/lib/utils"; +import { AppHero } from "../app-hero"; +import { ExplorerLink } from "../cluster/cluster-ui"; +import { WalletButton } from "../solana/solana-provider"; +import { useAblTokenProgram } from "./abl-token-data-access"; +import { AblTokenCreate, AblTokenProgram } from "./abl-token-ui"; export default function AblTokenFeature() { - const { publicKey } = useWallet() - const { programId } = useAblTokenProgram() + const { publicKey } = useWallet(); + const { programId } = useAblTokenProgram(); return publicKey ? (
@@ -30,5 +30,5 @@ export default function AblTokenFeature() {
- ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token-detail.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token-detail.tsx index 22e811a7d..051b98773 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token-detail.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token-detail.tsx @@ -1,13 +1,13 @@ -'use client' +"use client"; -import { useWallet } from '@solana/wallet-adapter-react' -import { WalletButton } from '../solana/solana-provider' -import { useParams } from 'next/navigation' -import React from 'react' -import { useAblTokenProgram, useGetToken } from './abl-token-data-access' -import { PublicKey } from '@solana/web3.js' -import { BN } from '@anchor-lang/core' -import { Button } from '@/components/ui/button' +import { BN } from "@anchor-lang/core"; +import { useWallet } from "@solana/wallet-adapter-react"; +import { PublicKey } from "@solana/web3.js"; +import { useParams } from "next/navigation"; +import React from "react"; +import { Button } from "@/components/ui/button"; +import { WalletButton } from "../solana/solana-provider"; +import { useAblTokenProgram, useGetToken } from "./abl-token-data-access"; interface TokenInfo { address: string; @@ -27,7 +27,7 @@ interface TokenInfo { } function TokenInfo({ tokenAddress }: { tokenAddress: string }) { - const { attachToExistingToken } = useAblTokenProgram() + const { attachToExistingToken } = useAblTokenProgram(); const tokenInfo = useGetToken(new PublicKey(tokenAddress)); return (
@@ -43,16 +43,25 @@ function TokenInfo({ tokenAddress }: { tokenAddress: string }) {
Mint Authority: {tokenInfo.data?.mintAuthority?.toString()}
Freeze Authority: {tokenInfo.data?.freezeAuthority?.toString()}
Permanent Delegate: {tokenInfo.data?.permanentDelegate?.toString()}
-
+

ABL Token

Mode: {tokenInfo.data?.mode}
Threshold: {tokenInfo.data?.threshold?.toString()}
- {tokenInfo.data?.isTransferHookEnabled ? (tokenInfo.data?.isTransferHookSet ? ( -
TxHook: Enabled and Set ✅
+ {tokenInfo.data?.isTransferHookEnabled ? ( + tokenInfo.data?.isTransferHookSet ? ( +
TxHook: Enabled and Set ✅
+ ) : ( +
+ TxHook: Enabled.{" "} + +
+ ) ) : ( -
TxHook: Enabled.
- )) : (
TxHook: Not enabled ❌
)}
@@ -61,15 +70,15 @@ function TokenInfo({ tokenAddress }: { tokenAddress: string }) {

No token information available.

)}
- ) + ); } function TokenManagement({ tokenInfo }: { tokenInfo: TokenInfo }) { - const { publicKey } = useWallet() - const { changeMode, mintTo } = useAblTokenProgram() - const [mode, setMode] = React.useState<'Allow' | 'Block' | 'Mixed'>(tokenInfo.mode as 'Allow' | 'Block' | 'Mixed') - const [threshold, setThreshold] = React.useState(tokenInfo.threshold ?? undefined) - const [destinationWallet, setDestinationWallet] = React.useState('') + const { publicKey } = useWallet(); + const { changeMode, mintTo } = useAblTokenProgram(); + const [mode, setMode] = React.useState<"Allow" | "Block" | "Mixed">(tokenInfo.mode as "Allow" | "Block" | "Mixed"); + const [threshold, setThreshold] = React.useState(tokenInfo.threshold ?? undefined); + const [destinationWallet, setDestinationWallet] = React.useState(""); const handleApplyChanges = async () => { if (!publicKey || !tokenInfo) return; @@ -81,11 +90,11 @@ function TokenManagement({ tokenInfo }: { tokenInfo: TokenInfo }) { mint: new PublicKey(tokenInfo.address), }); } catch (err) { - console.error('Failed to apply changes:', err); + console.error("Failed to apply changes:", err); } }; - const [mintAmount, setMintAmount] = React.useState('0') + const [mintAmount, setMintAmount] = React.useState("0"); const handleMint = async () => { if (!publicKey || !tokenInfo) return; @@ -96,9 +105,9 @@ function TokenManagement({ tokenInfo }: { tokenInfo: TokenInfo }) { amount: new BN(mintAmount), recipient: publicKey, }); - console.log('Minted successfully'); + console.log("Minted successfully"); } catch (err) { - console.error('Failed to mint tokens:', err); + console.error("Failed to mint tokens:", err); } }; @@ -109,56 +118,64 @@ function TokenManagement({ tokenInfo }: { tokenInfo: TokenInfo }) {
{tokenInfo.isTransferHookSet && (
- +

Mode

- {mode === 'Mixed' && ( -
- - setThreshold(e.target.value)} - min="0" - /> -
+ {mode === "Mixed" && ( +
+ + setThreshold(e.target.value)} + min="0" + /> +
)}
-
-
)}
@@ -167,12 +184,15 @@ function TokenManagement({ tokenInfo }: { tokenInfo: TokenInfo }) {

Mint New Tokens

- + setDestinationWallet(e.target.value)} + onChange={(e) => setDestinationWallet(e.target.value)} placeholder="Enter destination wallet address" />
@@ -181,25 +201,23 @@ function TokenManagement({ tokenInfo }: { tokenInfo: TokenInfo }) { type="number" className="w-full p-2 border rounded" value={mintAmount} - onChange={e => setMintAmount(e.target.value)} + onChange={(e) => setMintAmount(e.target.value)} min="0" placeholder="Amount to mint" /> - +
- ) + ); } export default function ManageTokenDetail() { - const { publicKey } = useWallet() - const params = useParams() - const tokenAddress = params?.address as string + const { publicKey } = useWallet(); + const params = useParams(); + const tokenAddress = params?.address as string; const tokenQuery = useGetToken(new PublicKey(tokenAddress)); const tokenInfo = React.useMemo(() => { @@ -218,7 +236,7 @@ export default function ManageTokenDetail() { - ) + ); } return ( @@ -230,10 +248,9 @@ export default function ManageTokenDetail() { ) : ( <> - {tokenInfo && } - + {tokenInfo && } )} - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token-input.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token-input.tsx index 1f5a1695c..dd046f99a 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token-input.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token-input.tsx @@ -1,22 +1,21 @@ -'use client' +"use client"; -import { useWallet } from '@solana/wallet-adapter-react' -import { WalletButton } from '../solana/solana-provider' - -import { redirect } from 'next/navigation' -import React from 'react' -import { Button } from '@/components/ui/button' +import { useWallet } from "@solana/wallet-adapter-react"; +import { redirect } from "next/navigation"; +import React from "react"; +import { Button } from "@/components/ui/button"; +import { WalletButton } from "../solana/solana-provider"; export default function ManageTokenInput() { - const { publicKey } = useWallet() - const [tokenAddress, setTokenAddress] = React.useState('') + const { publicKey } = useWallet(); + const [tokenAddress, setTokenAddress] = React.useState(""); const handleSubmit = (e: React.FormEvent) => { - e.preventDefault() + e.preventDefault(); if (tokenAddress) { - redirect(`/manage-token/${tokenAddress.toString()}`) + redirect(`/manage-token/${tokenAddress.toString()}`); } - } + }; if (!publicKey) { return ( @@ -25,7 +24,7 @@ export default function ManageTokenInput() { - ) + ); } return ( @@ -39,17 +38,15 @@ export default function ManageTokenInput() { type="text" className="w-full p-2 border rounded" value={tokenAddress} - onChange={e => setTokenAddress(e.target.value)} + onChange={(e) => setTokenAddress(e.target.value)} placeholder="Enter token address" required /> - + - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token.tsx index feab86b70..8ada87843 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-manage-token.tsx @@ -1,11 +1,11 @@ -'use client' +"use client"; -import { useWallet } from '@solana/wallet-adapter-react' -import { WalletButton } from '../solana/solana-provider' -import { AppHero } from '../app-hero' -import ManageTokenInput from './abl-token-manage-token-input' +import { useWallet } from "@solana/wallet-adapter-react"; +import { AppHero } from "../app-hero"; +import { WalletButton } from "../solana/solana-provider"; +import ManageTokenInput from "./abl-token-manage-token-input"; export default function AblTokenFeature() { - const { publicKey } = useWallet() + const { publicKey } = useWallet(); return publicKey ? (
@@ -21,5 +21,5 @@ export default function AblTokenFeature() {
- ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-new-token.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-new-token.tsx index ed0bb438e..9a489a1d7 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-new-token.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-new-token.tsx @@ -1,16 +1,16 @@ -'use client' +"use client"; -import { useWallet } from '@solana/wallet-adapter-react' -import { ExplorerLink } from '../cluster/cluster-ui' -import { WalletButton } from '../solana/solana-provider' -import { useAblTokenProgram } from './abl-token-data-access' -import { AblTokenCreate } from './abl-token-ui' -import { AppHero } from '../app-hero' -import { ellipsify } from '@/lib/utils' +import { useWallet } from "@solana/wallet-adapter-react"; +import { ellipsify } from "@/lib/utils"; +import { AppHero } from "../app-hero"; +import { ExplorerLink } from "../cluster/cluster-ui"; +import { WalletButton } from "../solana/solana-provider"; +import { useAblTokenProgram } from "./abl-token-data-access"; +import { AblTokenCreate } from "./abl-token-ui"; export default function AblTokenFeature() { - const { publicKey } = useWallet() - const { programId } = useAblTokenProgram() + const { publicKey } = useWallet(); + const { programId } = useAblTokenProgram(); return publicKey ? (
@@ -29,5 +29,5 @@ export default function AblTokenFeature() {
- ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-ui.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-ui.tsx index 6c0b7ff7b..8293a3892 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-ui.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/abl-token/abl-token-ui.tsx @@ -1,34 +1,33 @@ -'use client' +"use client"; -import { PublicKey } from '@solana/web3.js' -import { useAblTokenProgram } from './abl-token-data-access' -import { Button } from '@/components/ui/button' -import { BN } from '@anchor-lang/core' -import React from 'react' -import { useWallet } from '@solana/wallet-adapter-react' +import { BN } from "@anchor-lang/core"; +import { useWallet } from "@solana/wallet-adapter-react"; +import { PublicKey } from "@solana/web3.js"; +import React from "react"; +import { Button } from "@/components/ui/button"; +import { useAblTokenProgram } from "./abl-token-data-access"; export function AblTokenCreate() { - - const { publicKey } = useWallet() - const { initToken } = useAblTokenProgram() - const [mode, setMode] = React.useState<'allow' | 'block' | 'threshold'>('allow') - const [threshold, setThreshold] = React.useState('100000') + const { publicKey } = useWallet(); + const { initToken } = useAblTokenProgram(); + const [mode, setMode] = React.useState<"allow" | "block" | "threshold">("allow"); + const [threshold, setThreshold] = React.useState("100000"); const [formData, setFormData] = React.useState({ - mintAuthority: publicKey ? publicKey.toString() : '', - freezeAuthority: publicKey ? publicKey.toString() : '', - permanentDelegate: publicKey ? publicKey.toString() : '', - transferHookAuthority: publicKey ? publicKey.toString() : '', - name: '', - symbol: '', - uri: '', - decimals: '6' - }) + mintAuthority: publicKey ? publicKey.toString() : "", + freezeAuthority: publicKey ? publicKey.toString() : "", + permanentDelegate: publicKey ? publicKey.toString() : "", + transferHookAuthority: publicKey ? publicKey.toString() : "", + name: "", + symbol: "", + uri: "", + decimals: "6", + }); const handleSubmit = (e: React.FormEvent) => { - e.preventDefault() + e.preventDefault(); try { initToken.mutateAsync({ - decimals: parseInt(formData.decimals), + decimals: parseInt(formData.decimals, 10), mintAuthority: new PublicKey(formData.mintAuthority), freezeAuthority: new PublicKey(formData.freezeAuthority), permanentDelegate: new PublicKey(formData.permanentDelegate), @@ -37,12 +36,12 @@ export function AblTokenCreate() { threshold: new BN(threshold), name: formData.name, symbol: formData.symbol, - uri: formData.uri - }) + uri: formData.uri, + }); } catch (err) { - console.error('Invalid form data:', err) + console.error("Invalid form data:", err); } - } + }; return (
@@ -53,7 +52,7 @@ export function AblTokenCreate() { type="text" className="w-full p-2 border rounded" value={formData.mintAuthority} - onChange={e => setFormData({...formData, mintAuthority: e.target.value})} + onChange={(e) => setFormData({ ...formData, mintAuthority: e.target.value })} required /> @@ -64,7 +63,7 @@ export function AblTokenCreate() { type="text" className="w-full p-2 border rounded" value={formData.freezeAuthority} - onChange={e => setFormData({...formData, freezeAuthority: e.target.value})} + onChange={(e) => setFormData({ ...formData, freezeAuthority: e.target.value })} required /> @@ -75,7 +74,7 @@ export function AblTokenCreate() { type="text" className="w-full p-2 border rounded" value={formData.permanentDelegate} - onChange={e => setFormData({...formData, permanentDelegate: e.target.value})} + onChange={(e) => setFormData({ ...formData, permanentDelegate: e.target.value })} required /> @@ -86,7 +85,12 @@ export function AblTokenCreate() { type="text" className="w-full p-2 border rounded" value={formData.transferHookAuthority} - onChange={e => setFormData({...formData, transferHookAuthority: e.target.value})} + onChange={(e) => + setFormData({ + ...formData, + transferHookAuthority: e.target.value, + }) + } required /> @@ -97,7 +101,7 @@ export function AblTokenCreate() { type="text" className="w-full p-2 border rounded" value={formData.name} - onChange={e => setFormData({...formData, name: e.target.value})} + onChange={(e) => setFormData({ ...formData, name: e.target.value })} required /> @@ -108,7 +112,7 @@ export function AblTokenCreate() { type="text" className="w-full p-2 border rounded" value={formData.symbol} - onChange={e => setFormData({...formData, symbol: e.target.value})} + onChange={(e) => setFormData({ ...formData, symbol: e.target.value })} required /> @@ -119,7 +123,7 @@ export function AblTokenCreate() { type="text" className="w-full p-2 border rounded" value={formData.uri} - onChange={e => setFormData({...formData, uri: e.target.value})} + onChange={(e) => setFormData({ ...formData, uri: e.target.value })} required /> @@ -130,7 +134,7 @@ export function AblTokenCreate() { type="number" className="w-full p-2 border rounded" value={formData.decimals} - onChange={e => setFormData({...formData, decimals: e.target.value})} + onChange={(e) => setFormData({ ...formData, decimals: e.target.value })} required min="0" max="9" @@ -138,43 +142,29 @@ export function AblTokenCreate() {
- +

Mode*

- {mode === 'threshold' && ( + {mode === "threshold" && ( @@ -182,35 +172,35 @@ export function AblTokenCreate() {
- ) + ); } export function AblTokenProgram() { - const { getProgramAccount } = useAblTokenProgram() + const { getProgramAccount } = useAblTokenProgram(); if (getProgramAccount.isLoading) { - return + return ; } if (!getProgramAccount.data?.value) { return (
Program account not found. Make sure you have deployed the program and are on the correct cluster.
- ) + ); } return ( -
+
{JSON.stringify(getProgramAccount.data.value, null, 2)}
- ) + ); } interface WalletEntry { address: string; - mode: 'allow' | 'block'; + mode: "allow" | "block"; } export function AblTokenWalletTable() { @@ -224,24 +214,24 @@ export function AblTokenWalletTable() { e.preventDefault(); const file = e.dataTransfer.files[0]; - if (file && file.type === 'text/csv') { + if (file && file.type === "text/csv") { const text = await file.text(); - const rows = text.split('\n'); - + const rows = text.split("\n"); + const parsed: WalletEntry[] = rows - .filter(row => row.trim()) // Skip empty rows - .map(row => { - const [address, mode] = row.split(',').map(field => field.trim()); + .filter((row) => row.trim()) // Skip empty rows + .map((row) => { + const [address, mode] = row.split(",").map((field) => field.trim()); return { address, - mode: mode.toLowerCase() as 'allow' | 'block' + mode: mode.toLowerCase() as "allow" | "block", }; }) - .filter(entry => { + .filter((entry) => { // Basic validation try { new PublicKey(entry.address); - return ['allow', 'block'].includes(entry.mode); + return ["allow", "block"].includes(entry.mode); } catch { return false; } @@ -253,13 +243,14 @@ export function AblTokenWalletTable() { return (
-
Drop CSV file here (address,mode) -
+ {wallets.length > 0 && (
@@ -271,11 +262,11 @@ export function AblTokenWalletTable() { - {wallets.map((wallet, index) => ( - + {wallets.map((wallet) => ( + {wallet.address} - + {wallet.mode} diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-data-access.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-data-access.tsx index 2d67047b8..bec06323a 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-data-access.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-data-access.tsx @@ -1,77 +1,101 @@ -'use client' +"use client"; -import { createAssociatedTokenAccountIdempotentInstruction, createTransferCheckedInstruction, getAssociatedTokenAddressSync, getExtraAccountMetaAddress, getMint, getTransferHook, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token' -import { useConnection, useWallet } from '@solana/wallet-adapter-react' +import { Buffer } from "node:buffer"; import { - Connection, + createAssociatedTokenAccountIdempotentInstruction, + createTransferCheckedInstruction, + getAssociatedTokenAddressSync, + getExtraAccountMetaAddress, + getMint, + getTransferHook, + TOKEN_2022_PROGRAM_ID, + TOKEN_PROGRAM_ID, +} from "@solana/spl-token"; +import { useConnection, useWallet } from "@solana/wallet-adapter-react"; +import { + type Connection, LAMPORTS_PER_SOL, PublicKey, SystemProgram, Transaction, TransactionMessage, - TransactionSignature, + type TransactionSignature, VersionedTransaction, -} from '@solana/web3.js' -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' -import { useTransactionErrorToast, useTransactionToast } from '../use-transaction-toast' -import { useAnchorProvider } from '../solana/solana-provider' -import { Buffer } from "buffer" +} from "@solana/web3.js"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { useAnchorProvider } from "../solana/solana-provider"; +import { useTransactionErrorToast, useTransactionToast } from "../use-transaction-toast"; export function useGetBalance({ address }: { address: PublicKey }) { - const { connection } = useConnection() + const { connection } = useConnection(); return useQuery({ - queryKey: ['get-balance', { endpoint: connection.rpcEndpoint, address }], + queryKey: ["get-balance", { endpoint: connection.rpcEndpoint, address }], queryFn: () => connection.getBalance(address), - }) + }); } export function useGetSignatures({ address }: { address: PublicKey }) { - const { connection } = useConnection() + const { connection } = useConnection(); return useQuery({ - queryKey: ['get-signatures', { endpoint: connection.rpcEndpoint, address }], + queryKey: ["get-signatures", { endpoint: connection.rpcEndpoint, address }], queryFn: () => connection.getSignaturesForAddress(address), - }) + }); } export function useSendTokens() { - const { connection } = useConnection() - const { publicKey } = useWallet() - const transactionToast = useTransactionToast() - const provider = useAnchorProvider() - const transactionErrorToast = useTransactionErrorToast() + const { connection } = useConnection(); + const { publicKey } = useWallet(); + const transactionToast = useTransactionToast(); + const provider = useAnchorProvider(); + const transactionErrorToast = useTransactionErrorToast(); return useMutation({ - mutationFn: async (args: { - mint: PublicKey, - destination: PublicKey, - amount: number, - }) => { - if (!publicKey) throw new Error('No public key found'); + mutationFn: async (args: { mint: PublicKey; destination: PublicKey; amount: number }) => { + if (!publicKey) throw new Error("No public key found"); const { mint, destination, amount } = args; - const mintInfo = await getMint(connection, mint, 'confirmed', TOKEN_2022_PROGRAM_ID); + const mintInfo = await getMint(connection, mint, "confirmed", TOKEN_2022_PROGRAM_ID); const ataDestination = getAssociatedTokenAddressSync(mint, destination, true, TOKEN_2022_PROGRAM_ID); const ataSource = getAssociatedTokenAddressSync(mint, publicKey, true, TOKEN_2022_PROGRAM_ID); - const ix = createAssociatedTokenAccountIdempotentInstruction(publicKey, ataDestination, destination, mint, TOKEN_2022_PROGRAM_ID); + const ix = createAssociatedTokenAccountIdempotentInstruction( + publicKey, + ataDestination, + destination, + mint, + TOKEN_2022_PROGRAM_ID, + ); const bi = BigInt(amount); const decimals = mintInfo.decimals; - const ix3 = await createTransferCheckedInstruction(ataSource, mint, ataDestination, publicKey, bi, decimals, undefined, TOKEN_2022_PROGRAM_ID); + const ix3 = await createTransferCheckedInstruction( + ataSource, + mint, + ataDestination, + publicKey, + bi, + decimals, + undefined, + TOKEN_2022_PROGRAM_ID, + ); const transferHook = getTransferHook(mintInfo); - if (!transferHook) throw new Error('bad token'); + if (!transferHook) throw new Error("bad token"); const extraMetas = getExtraAccountMetaAddress(mint, transferHook.programId); - const seeds = [Buffer.from('ab_wallet'), destination.toBuffer()]; + const seeds = [Buffer.from("ab_wallet"), destination.toBuffer()]; const abWallet = PublicKey.findProgramAddressSync(seeds, transferHook.programId)[0]; ix3.keys.push({ pubkey: abWallet, isSigner: false, isWritable: false }); - ix3.keys.push({ pubkey: transferHook.programId, isSigner: false, isWritable: false }); + ix3.keys.push({ + pubkey: transferHook.programId, + isSigner: false, + isWritable: false, + }); ix3.keys.push({ pubkey: extraMetas, isSigner: false, isWritable: false }); - - const validateStateAccount = await connection.getAccountInfo(extraMetas, 'confirmed'); - if (!validateStateAccount) throw new Error('validate-state-account not found'); + + const validateStateAccount = await connection.getAccountInfo(extraMetas, "confirmed"); + if (!validateStateAccount) throw new Error("validate-state-account not found"); const transaction = new Transaction(); transaction.add(ix, ix3); @@ -83,17 +107,19 @@ export function useSendTokens() { return connection.sendRawTransaction(signedTx.serialize()); }, onSuccess: (signature) => { - transactionToast(signature) + transactionToast(signature); + }, + onError: (error) => { + transactionErrorToast(error, connection); }, - onError: (error) => { transactionErrorToast(error, connection) }, - }) + }); } export function useGetTokenAccounts({ address }: { address: PublicKey }) { - const { connection } = useConnection() + const { connection } = useConnection(); return useQuery({ - queryKey: ['get-token-accounts', { endpoint: connection.rpcEndpoint, address }], + queryKey: ["get-token-accounts", { endpoint: connection.rpcEndpoint, address }], queryFn: async () => { const [tokenAccounts, token2022Accounts] = await Promise.all([ connection.getParsedTokenAccountsByOwner(address, { @@ -102,96 +128,96 @@ export function useGetTokenAccounts({ address }: { address: PublicKey }) { connection.getParsedTokenAccountsByOwner(address, { programId: TOKEN_2022_PROGRAM_ID, }), - ]) - return [...tokenAccounts.value, ...token2022Accounts.value] + ]); + return [...tokenAccounts.value, ...token2022Accounts.value]; }, - }) + }); } export function useTransferSol({ address }: { address: PublicKey }) { - const { connection } = useConnection() + const { connection } = useConnection(); // const transactionToast = useTransactionToast() - const wallet = useWallet() - const client = useQueryClient() + const wallet = useWallet(); + const client = useQueryClient(); return useMutation({ - mutationKey: ['transfer-sol', { endpoint: connection.rpcEndpoint, address }], + mutationKey: ["transfer-sol", { endpoint: connection.rpcEndpoint, address }], mutationFn: async (input: { destination: PublicKey; amount: number }) => { - let signature: TransactionSignature = '' + let signature: TransactionSignature = ""; try { const { transaction, latestBlockhash } = await createTransaction({ publicKey: address, destination: input.destination, amount: input.amount, connection, - }) + }); // Send transaction and await for signature - signature = await wallet.sendTransaction(transaction, connection) + signature = await wallet.sendTransaction(transaction, connection); // Send transaction and await for signature - await connection.confirmTransaction({ signature, ...latestBlockhash }, 'confirmed') + await connection.confirmTransaction({ signature, ...latestBlockhash }, "confirmed"); - console.log(signature) - return signature + console.log(signature); + return signature; } catch (error: unknown) { - console.log('error', `Transaction failed! ${error}`, signature) + console.log("error", `Transaction failed! ${error}`, signature); - return + return; } }, onSuccess: (signature) => { if (signature) { // TODO: Add back Toast // transactionToast(signature) - console.log('Transaction sent', signature) + console.log("Transaction sent", signature); } return Promise.all([ client.invalidateQueries({ - queryKey: ['get-balance', { endpoint: connection.rpcEndpoint, address }], + queryKey: ["get-balance", { endpoint: connection.rpcEndpoint, address }], }), client.invalidateQueries({ - queryKey: ['get-signatures', { endpoint: connection.rpcEndpoint, address }], + queryKey: ["get-signatures", { endpoint: connection.rpcEndpoint, address }], }), - ]) + ]); }, onError: (error) => { // TODO: Add Toast - console.error(`Transaction failed! ${error}`) + console.error(`Transaction failed! ${error}`); }, - }) + }); } export function useRequestAirdrop({ address }: { address: PublicKey }) { - const { connection } = useConnection() + const { connection } = useConnection(); // const transactionToast = useTransactionToast() - const client = useQueryClient() + const client = useQueryClient(); return useMutation({ - mutationKey: ['airdrop', { endpoint: connection.rpcEndpoint, address }], + mutationKey: ["airdrop", { endpoint: connection.rpcEndpoint, address }], mutationFn: async (amount: number = 1) => { const [latestBlockhash, signature] = await Promise.all([ connection.getLatestBlockhash(), connection.requestAirdrop(address, amount * LAMPORTS_PER_SOL), - ]) + ]); - await connection.confirmTransaction({ signature, ...latestBlockhash }, 'confirmed') - return signature + await connection.confirmTransaction({ signature, ...latestBlockhash }, "confirmed"); + return signature; }, onSuccess: (signature) => { // TODO: Add back Toast // transactionToast(signature) - console.log('Airdrop sent', signature) + console.log("Airdrop sent", signature); return Promise.all([ client.invalidateQueries({ - queryKey: ['get-balance', { endpoint: connection.rpcEndpoint, address }], + queryKey: ["get-balance", { endpoint: connection.rpcEndpoint, address }], }), client.invalidateQueries({ - queryKey: ['get-signatures', { endpoint: connection.rpcEndpoint, address }], + queryKey: ["get-signatures", { endpoint: connection.rpcEndpoint, address }], }), - ]) + ]); }, - }) + }); } async function createTransaction({ @@ -200,16 +226,16 @@ async function createTransaction({ amount, connection, }: { - publicKey: PublicKey - destination: PublicKey - amount: number - connection: Connection + publicKey: PublicKey; + destination: PublicKey; + amount: number; + connection: Connection; }): Promise<{ - transaction: VersionedTransaction - latestBlockhash: { blockhash: string; lastValidBlockHeight: number } + transaction: VersionedTransaction; + latestBlockhash: { blockhash: string; lastValidBlockHeight: number }; }> { // Get the latest blockhash to use in our transaction - const latestBlockhash = await connection.getLatestBlockhash() + const latestBlockhash = await connection.getLatestBlockhash(); // Create instructions to send, in this case a simple transfer const instructions = [ @@ -218,20 +244,20 @@ async function createTransaction({ toPubkey: destination, lamports: amount * LAMPORTS_PER_SOL, }), - ] + ]; // Create a new TransactionMessage with version and compile it to legacy const messageLegacy = new TransactionMessage({ payerKey: publicKey, recentBlockhash: latestBlockhash.blockhash, instructions, - }).compileToLegacyMessage() + }).compileToLegacyMessage(); // Create a new VersionedTransaction which supports legacy and v0 - const transaction = new VersionedTransaction(messageLegacy) + const transaction = new VersionedTransaction(messageLegacy); return { transaction, latestBlockhash, - } + }; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-detail-feature.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-detail-feature.tsx index 4aa2efc7b..4e186d8cf 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-detail-feature.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-detail-feature.tsx @@ -1,27 +1,27 @@ -'use client' +"use client"; -import { PublicKey } from '@solana/web3.js' -import { useMemo } from 'react' -import { useParams } from 'next/navigation' -import { ExplorerLink } from '../cluster/cluster-ui' -import { AccountBalance, AccountButtons, AccountTokens, AccountTransactions } from './account-ui' -import { AppHero } from '../app-hero' -import { ellipsify } from '@/lib/utils' +import { PublicKey } from "@solana/web3.js"; +import { useParams } from "next/navigation"; +import { useMemo } from "react"; +import { ellipsify } from "@/lib/utils"; +import { AppHero } from "../app-hero"; +import { ExplorerLink } from "../cluster/cluster-ui"; +import { AccountBalance, AccountButtons, AccountTokens, AccountTransactions } from "./account-ui"; export default function AccountDetailFeature() { - const params = useParams() + const params = useParams(); const address = useMemo(() => { if (!params.address) { - return + return; } try { - return new PublicKey(params.address) + return new PublicKey(params.address); } catch (e) { - console.log(`Invalid public key`, e) + console.log(`Invalid public key`, e); } - }, [params]) + }, [params]); if (!address) { - return
Error loading account
+ return
Error loading account
; } return ( @@ -43,5 +43,5 @@ export default function AccountDetailFeature() {
- ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-list-feature.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-list-feature.tsx index 4ccb10390..b7559c0c9 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-list-feature.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-list-feature.tsx @@ -1,15 +1,14 @@ -'use client' +"use client"; -import { useWallet } from '@solana/wallet-adapter-react' -import { WalletButton } from '../solana/solana-provider' - -import { redirect } from 'next/navigation' +import { useWallet } from "@solana/wallet-adapter-react"; +import { redirect } from "next/navigation"; +import { WalletButton } from "../solana/solana-provider"; export default function AccountListFeature() { - const { publicKey } = useWallet() + const { publicKey } = useWallet(); if (publicKey) { - return redirect(`/account/${publicKey.toString()}`) + return redirect(`/account/${publicKey.toString()}`); } return ( @@ -18,5 +17,5 @@ export default function AccountListFeature() {
- ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-ui.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-ui.tsx index 5b972960e..fa19f8dc6 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-ui.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/account/account-ui.tsx @@ -1,13 +1,19 @@ -'use client' +"use client"; -import { useWallet } from '@solana/wallet-adapter-react' -import { LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js' -import { RefreshCw } from 'lucide-react' -import { useQueryClient } from '@tanstack/react-query' -import { useMemo, useState } from 'react' - -import { useCluster } from '../cluster/cluster-data-access' -import { ExplorerLink } from '../cluster/cluster-ui' +import { useWallet } from "@solana/wallet-adapter-react"; +import { LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js"; +import { useQueryClient } from "@tanstack/react-query"; +import { RefreshCw } from "lucide-react"; +import { useMemo, useState } from "react"; +import { AppAlert } from "@/components/app-alert"; +import { AppModal } from "@/components/app-modal"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; +import { ellipsify } from "@/lib/utils"; +import { useCluster } from "../cluster/cluster-data-access"; +import { ExplorerLink } from "../cluster/cluster-ui"; import { useGetBalance, useGetSignatures, @@ -15,40 +21,33 @@ import { useRequestAirdrop, useSendTokens, useTransferSol, -} from './account-data-access' -import { ellipsify } from '@/lib/utils' -import { Button } from '@/components/ui/button' -import { AppAlert } from '@/components/app-alert' -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table' -import { AppModal } from '@/components/app-modal' -import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' +} from "./account-data-access"; export function AccountBalance({ address }: { address: PublicKey }) { - const query = useGetBalance({ address }) + const query = useGetBalance({ address }); return ( -

query.refetch()}> - {query.data ? : '...'} SOL -

- ) + + ); } export function AccountChecker() { - const { publicKey } = useWallet() + const { publicKey } = useWallet(); if (!publicKey) { - return null + return null; } - return + return ; } export function AccountBalanceCheck({ address }: { address: PublicKey }) { - const { cluster } = useCluster() - const mutation = useRequestAirdrop({ address }) - const query = useGetBalance({ address }) + const { cluster } = useCluster(); + const mutation = useRequestAirdrop({ address }); + const query = useGetBalance({ address }); if (query.isLoading) { - return null + return null; } if (query.isError || !query.data) { return ( @@ -61,33 +60,33 @@ export function AccountBalanceCheck({ address }: { address: PublicKey }) { > You are connected to {cluster.name} but your account is not found on this cluster. - ) + ); } - return null + return null; } export function AccountButtons({ address }: { address: PublicKey }) { - const { cluster } = useCluster() + const { cluster } = useCluster(); return (
- {cluster.network?.includes('mainnet') ? null : } + {cluster.network?.includes("mainnet") ? null : }
- ) + ); } export function AccountTokens({ address }: { address: PublicKey }) { - const [showAll, setShowAll] = useState(false) - const query = useGetTokenAccounts({ address }) - const client = useQueryClient() - const sendTokens = useSendTokens() + const [showAll, setShowAll] = useState(false); + const query = useGetTokenAccounts({ address }); + const client = useQueryClient(); + const sendTokens = useSendTokens(); const items = useMemo(() => { - if (showAll) return query.data - return query.data?.slice(0, 5) - }, [query.data, showAll]) + if (showAll) return query.data; + return query.data?.slice(0, 5); + }, [query.data, showAll]); return (
@@ -101,10 +100,10 @@ export function AccountTokens({ address }: { address: PublicKey }) { + }} + > + Send + @@ -181,7 +184,7 @@ export function AccountTokens({ address }: { address: PublicKey }) { @@ -192,17 +195,17 @@ export function AccountTokens({ address }: { address: PublicKey }) {
)} - ) + ); } export function AccountTransactions({ address }: { address: PublicKey }) { - const query = useGetSignatures({ address }) - const [showAll, setShowAll] = useState(false) + const query = useGetSignatures({ address }); + const [showAll, setShowAll] = useState(false); const items = useMemo(() => { - if (showAll) return query.data - return query.data?.slice(0, 5) - }, [query.data, showAll]) + if (showAll) return query.data; + return query.data?.slice(0, 5); + }, [query.data, showAll]); return (
@@ -258,7 +261,7 @@ export function AccountTransactions({ address }: { address: PublicKey }) { @@ -269,11 +272,11 @@ export function AccountTransactions({ address }: { address: PublicKey }) {
)} - ) + ); } function BalanceSol({ balance }: { balance: number }) { - return {Math.round((balance / LAMPORTS_PER_SOL) * 100000) / 100000} + return {Math.round((balance / LAMPORTS_PER_SOL) * 100000) / 100000}; } function ModalReceive({ address }: { address: PublicKey }) { @@ -282,12 +285,12 @@ function ModalReceive({ address }: { address: PublicKey }) {

Receive assets by sending them to your public key:

{address.toString()} - ) + ); } function ModalAirdrop({ address }: { address: PublicKey }) { - const mutation = useRequestAirdrop({ address }) - const [amount, setAmount] = useState('2') + const mutation = useRequestAirdrop({ address }); + const [amount, setAmount] = useState("2"); return ( - ) + ); } function ModalSend({ address }: { address: PublicKey }) { - const wallet = useWallet() - const mutation = useTransferSol({ address }) - const [destination, setDestination] = useState('') - const [amount, setAmount] = useState('1') + const wallet = useWallet(); + const mutation = useTransferSol({ address }); + const [destination, setDestination] = useState(""); + const [amount, setAmount] = useState("1"); if (!address || !wallet.sendTransaction) { - return
Wallet not connected
+ return
Wallet not connected
; } return ( @@ -330,7 +333,7 @@ function ModalSend({ address }: { address: PublicKey }) { mutation.mutateAsync({ destination: new PublicKey(destination), amount: parseFloat(amount), - }) + }); }} > @@ -354,5 +357,5 @@ function ModalSend({ address }: { address: PublicKey }) { value={amount} /> - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-alert.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-alert.tsx index 008d7aaa6..d55b71a70 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-alert.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-alert.tsx @@ -1,6 +1,6 @@ -import { AlertCircle } from 'lucide-react' -import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' -import { ReactNode } from 'react' +import { AlertCircle } from "lucide-react"; +import type { ReactNode } from "react"; +import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; export function AppAlert({ action, children }: { action: ReactNode; children: ReactNode }) { return ( @@ -9,5 +9,5 @@ export function AppAlert({ action, children }: { action: ReactNode; children: Re {children} {action} - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-footer.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-footer.tsx index f871f95a9..783a2b653 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-footer.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-footer.tsx @@ -1,9 +1,7 @@ -import React from 'react' - export function AppFooter() { return (
- Generated by{' '} + Generated by{" "}
- ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-header.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-header.tsx index 1a3fa9e9f..44008df65 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-header.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-header.tsx @@ -1,19 +1,19 @@ -'use client' -import { usePathname } from 'next/navigation' -import { useState } from 'react' -import Link from 'next/link' -import { Button } from '@/components/ui/button' -import { Menu, X } from 'lucide-react' -import { ThemeSelect } from '@/components/theme-select' -import { ClusterUiSelect } from './cluster/cluster-ui' -import { WalletButton } from '@/components/solana/solana-provider' +"use client"; +import { Menu, X } from "lucide-react"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { useState } from "react"; +import { WalletButton } from "@/components/solana/solana-provider"; +import { ThemeSelect } from "@/components/theme-select"; +import { Button } from "@/components/ui/button"; +import { ClusterUiSelect } from "./cluster/cluster-ui"; export function AppHeader({ links = [] }: { links: { label: string; path: string }[] }) { - const pathname = usePathname() - const [showMenu, setShowMenu] = useState(false) + const pathname = usePathname(); + const [showMenu, setShowMenu] = useState(false); function isActive(path: string) { - return path === '/' ? pathname === '/' : pathname.startsWith(path) + return path === "/" ? pathname === "/" : pathname.startsWith(path); } return ( @@ -28,7 +28,7 @@ export function AppHeader({ links = [] }: { links: { label: string; path: string {links.map(({ label, path }) => (
  • {label} @@ -56,7 +56,7 @@ export function AppHeader({ links = [] }: { links: { label: string; path: string {links.map(({ label, path }) => (
  • setShowMenu(false)} > @@ -75,5 +75,5 @@ export function AppHeader({ links = [] }: { links: { label: string; path: string )} - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-hero.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-hero.tsx index 3e0b2946a..cbcc2eafa 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-hero.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-hero.tsx @@ -1,23 +1,23 @@ -import React from 'react' +import type React from "react"; export function AppHero({ children, subtitle, title, }: { - children?: React.ReactNode - subtitle?: React.ReactNode - title?: React.ReactNode + children?: React.ReactNode; + subtitle?: React.ReactNode; + title?: React.ReactNode; }) { return (
    - {typeof title === 'string' ?

    {title}

    : title} - {typeof subtitle === 'string' ?

    {subtitle}

    : subtitle} + {typeof title === "string" ?

    {title}

    : title} + {typeof subtitle === "string" ?

    {subtitle}

    : subtitle} {children}
    - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-layout.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-layout.tsx index 194008682..f6fde56be 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-layout.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-layout.tsx @@ -1,19 +1,19 @@ -'use client' +"use client"; -import { ThemeProvider } from './theme-provider' -import { Toaster } from './ui/sonner' -import { AppHeader } from '@/components/app-header' -import React from 'react' -import { AppFooter } from '@/components/app-footer' -import { ClusterChecker } from '@/components/cluster/cluster-ui' -import { AccountChecker } from '@/components/account/account-ui' +import type React from "react"; +import { AccountChecker } from "@/components/account/account-ui"; +import { AppFooter } from "@/components/app-footer"; +import { AppHeader } from "@/components/app-header"; +import { ClusterChecker } from "@/components/cluster/cluster-ui"; +import { ThemeProvider } from "./theme-provider"; +import { Toaster } from "./ui/sonner"; export function AppLayout({ children, links, }: { - children: React.ReactNode - links: { label: string; path: string }[] + children: React.ReactNode; + links: { label: string; path: string }[]; }) { return ( @@ -29,5 +29,5 @@ export function AppLayout({ - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-modal.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-modal.tsx index a302cd725..93ff4e474 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-modal.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-modal.tsx @@ -1,6 +1,6 @@ -import { Button } from '@/components/ui/button' -import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog' -import { ReactNode } from 'react' +import type { ReactNode } from "react"; +import { Button } from "@/components/ui/button"; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; export function AppModal({ children, @@ -9,11 +9,11 @@ export function AppModal({ submitDisabled, submitLabel, }: { - children: ReactNode - title: string - submit?: () => void - submitDisabled?: boolean - submitLabel?: string + children: ReactNode; + title: string; + submit?: () => void; + submitDisabled?: boolean; + submitLabel?: string; }) { return ( @@ -28,11 +28,11 @@ export function AppModal({ {submit ? ( ) : null} - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-providers.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-providers.tsx index a359b6541..c5a0e26da 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-providers.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/app-providers.tsx @@ -1,10 +1,10 @@ -'use client' +"use client"; -import { ThemeProvider } from '@/components/theme-provider' -import { ReactQueryProvider } from './react-query-provider' -import { ClusterProvider } from '@/components/cluster/cluster-data-access' -import { SolanaProvider } from '@/components/solana/solana-provider' -import React from 'react' +import type React from "react"; +import { ClusterProvider } from "@/components/cluster/cluster-data-access"; +import { SolanaProvider } from "@/components/solana/solana-provider"; +import { ThemeProvider } from "@/components/theme-provider"; +import { ReactQueryProvider } from "./react-query-provider"; export function AppProviders({ children }: Readonly<{ children: React.ReactNode }>) { return ( @@ -15,5 +15,5 @@ export function AppProviders({ children }: Readonly<{ children: React.ReactNode - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/cluster/cluster-data-access.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/cluster/cluster-data-access.tsx index 5a8d772b9..359fd3616 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/cluster/cluster-data-access.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/cluster/cluster-data-access.tsx @@ -1,22 +1,22 @@ -'use client' +"use client"; -import { clusterApiUrl, Connection } from '@solana/web3.js' -import { atom, useAtomValue, useSetAtom } from 'jotai' -import { atomWithStorage } from 'jotai/utils' -import { createContext, ReactNode, useContext } from 'react' +import { Connection, clusterApiUrl } from "@solana/web3.js"; +import { atom, useAtomValue, useSetAtom } from "jotai"; +import { atomWithStorage } from "jotai/utils"; +import { createContext, type ReactNode, useContext } from "react"; export interface SolanaCluster { - name: string - endpoint: string - network?: ClusterNetwork - active?: boolean + name: string; + endpoint: string; + network?: ClusterNetwork; + active?: boolean; } export enum ClusterNetwork { - Mainnet = 'mainnet-beta', - Testnet = 'testnet', - Devnet = 'devnet', - Custom = 'custom', + Mainnet = "mainnet-beta", + Testnet = "testnet", + Devnet = "devnet", + Custom = "custom", } // By default, we don't configure the mainnet-beta cluster @@ -24,94 +24,94 @@ export enum ClusterNetwork { // To use the mainnet-beta cluster, provide a custom endpoint export const defaultClusters: SolanaCluster[] = [ { - name: 'devnet', - endpoint: clusterApiUrl('devnet'), + name: "devnet", + endpoint: clusterApiUrl("devnet"), network: ClusterNetwork.Devnet, }, - { name: 'local', endpoint: 'http://localhost:8899' }, + { name: "local", endpoint: "http://localhost:8899" }, { - name: 'testnet', - endpoint: clusterApiUrl('testnet'), + name: "testnet", + endpoint: clusterApiUrl("testnet"), network: ClusterNetwork.Testnet, }, -] +]; -const clusterAtom = atomWithStorage('solana-cluster', defaultClusters[0]) -const clustersAtom = atomWithStorage('solana-clusters', defaultClusters) +const clusterAtom = atomWithStorage("solana-cluster", defaultClusters[0]); +const clustersAtom = atomWithStorage("solana-clusters", defaultClusters); const activeClustersAtom = atom((get) => { - const clusters = get(clustersAtom) - const cluster = get(clusterAtom) + const clusters = get(clustersAtom); + const cluster = get(clusterAtom); return clusters.map((item) => ({ ...item, active: item.name === cluster.name, - })) -}) + })); +}); const activeClusterAtom = atom((get) => { - const clusters = get(activeClustersAtom) + const clusters = get(activeClustersAtom); - return clusters.find((item) => item.active) || clusters[0] -}) + return clusters.find((item) => item.active) || clusters[0]; +}); export interface ClusterProviderContext { - cluster: SolanaCluster - clusters: SolanaCluster[] - addCluster: (cluster: SolanaCluster) => void - deleteCluster: (cluster: SolanaCluster) => void - setCluster: (cluster: SolanaCluster) => void + cluster: SolanaCluster; + clusters: SolanaCluster[]; + addCluster: (cluster: SolanaCluster) => void; + deleteCluster: (cluster: SolanaCluster) => void; + setCluster: (cluster: SolanaCluster) => void; - getExplorerUrl(path: string): string + getExplorerUrl(path: string): string; } -const Context = createContext({} as ClusterProviderContext) +const Context = createContext({} as ClusterProviderContext); export function ClusterProvider({ children }: { children: ReactNode }) { - const cluster = useAtomValue(activeClusterAtom) - const clusters = useAtomValue(activeClustersAtom) - const setCluster = useSetAtom(clusterAtom) - const setClusters = useSetAtom(clustersAtom) + const cluster = useAtomValue(activeClusterAtom); + const clusters = useAtomValue(activeClustersAtom); + const setCluster = useSetAtom(clusterAtom); + const setClusters = useSetAtom(clustersAtom); const value: ClusterProviderContext = { cluster, clusters: clusters.sort((a, b) => (a.name > b.name ? 1 : -1)), addCluster: (cluster: SolanaCluster) => { try { - new Connection(cluster.endpoint) - setClusters([...clusters, cluster]) + new Connection(cluster.endpoint); + setClusters([...clusters, cluster]); } catch (err) { - console.error(`${err}`) + console.error(`${err}`); } }, deleteCluster: (cluster: SolanaCluster) => { - setClusters(clusters.filter((item) => item.name !== cluster.name)) + setClusters(clusters.filter((item) => item.name !== cluster.name)); }, setCluster: (cluster: SolanaCluster) => setCluster(cluster), getExplorerUrl: (path: string) => `https://explorer.solana.com/${path}${getClusterUrlParam(cluster)}`, - } - return {children} + }; + return {children}; } export function useCluster() { - return useContext(Context) + return useContext(Context); } function getClusterUrlParam(cluster: SolanaCluster): string { - let suffix = '' + let suffix = ""; switch (cluster.network) { case ClusterNetwork.Devnet: - suffix = 'devnet' - break + suffix = "devnet"; + break; case ClusterNetwork.Mainnet: - suffix = '' - break + suffix = ""; + break; case ClusterNetwork.Testnet: - suffix = 'testnet' - break + suffix = "testnet"; + break; default: - suffix = `custom&customUrl=${encodeURIComponent(cluster.endpoint)}` - break + suffix = `custom&customUrl=${encodeURIComponent(cluster.endpoint)}`; + break; } - return suffix.length ? `?cluster=${suffix}` : '' + return suffix.length ? `?cluster=${suffix}` : ""; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/cluster/cluster-ui.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/cluster/cluster-ui.tsx index 66ac4ce05..99e1ac5b4 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/cluster/cluster-ui.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/cluster/cluster-ui.tsx @@ -1,18 +1,21 @@ -'use client' +"use client"; -import { useConnection } from '@solana/wallet-adapter-react' +import { useConnection } from "@solana/wallet-adapter-react"; -import { useQuery } from '@tanstack/react-query' -import * as React from 'react' -import { ReactNode } from 'react' - -import { useCluster } from './cluster-data-access' -import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu' -import { Button } from '@/components/ui/button' -import { AppAlert } from '@/components/app-alert' +import { useQuery } from "@tanstack/react-query"; +import type { ReactNode } from "react"; +import { AppAlert } from "@/components/app-alert"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { useCluster } from "./cluster-data-access"; export function ExplorerLink({ path, label, className }: { path: string; label: string; className?: string }) { - const { getExplorerUrl } = useCluster() + const { getExplorerUrl } = useCluster(); return (
    {label} - ) + ); } export function ClusterChecker({ children }: { children: ReactNode }) { - const { cluster } = useCluster() - const { connection } = useConnection() + const { cluster } = useCluster(); + const { connection } = useConnection(); const query = useQuery({ - queryKey: ['version', { cluster, endpoint: connection.rpcEndpoint }], + queryKey: ["version", { cluster, endpoint: connection.rpcEndpoint }], queryFn: () => connection.getVersion(), retry: 1, - }) + }); if (query.isLoading) { - return null + return null; } if (query.isError || !query.data) { return ( @@ -48,13 +51,13 @@ export function ClusterChecker({ children }: { children: ReactNode }) { > Error connecting to cluster {cluster.name}. - ) + ); } - return children + return children; } export function ClusterUiSelect() { - const { clusters, setCluster, cluster } = useCluster() + const { clusters, setCluster, cluster } = useCluster(); return ( @@ -68,5 +71,5 @@ export function ClusterUiSelect() { ))} - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/dashboard/dashboard-feature.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/dashboard/dashboard-feature.tsx index f6ddf48c2..77d01c47f 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/dashboard/dashboard-feature.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/dashboard/dashboard-feature.tsx @@ -1,12 +1,15 @@ -import { AppHero } from '@/components/app-hero' +import { AppHero } from "@/components/app-hero"; const links: { label: string; href: string }[] = [ - { label: 'Solana Docs', href: 'https://docs.solana.com/' }, - { label: 'Solana Faucet', href: 'https://faucet.solana.com/' }, - { label: 'Solana Cookbook', href: 'https://solana.com/developers/cookbook/' }, - { label: 'Solana Stack Overflow', href: 'https://solana.stackexchange.com/' }, - { label: 'Solana Developers GitHub', href: 'https://github.com/solana-developers/' }, -] + { label: "Solana Docs", href: "https://docs.solana.com/" }, + { label: "Solana Faucet", href: "https://faucet.solana.com/" }, + { label: "Solana Cookbook", href: "https://solana.com/developers/cookbook/" }, + { label: "Solana Stack Overflow", href: "https://solana.stackexchange.com/" }, + { + label: "Solana Developers GitHub", + href: "https://github.com/solana-developers/", + }, +]; export function DashboardFeature() { return ( @@ -15,8 +18,8 @@ export function DashboardFeature() {

    Here are some helpful links to get you started.

    - {links.map((link, index) => ( -
    + {links.map((link) => ( +
    - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/react-query-provider.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/react-query-provider.tsx index 2d4523ce6..6c3ca0bf6 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/react-query-provider.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/react-query-provider.tsx @@ -1,7 +1,7 @@ // Taken from https://tanstack.com/query/5/docs/framework/react/guides/advanced-ssr -'use client' +"use client"; -import { isServer, QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { isServer, QueryClient, QueryClientProvider } from "@tanstack/react-query"; function makeQueryClient() { return new QueryClient({ @@ -10,22 +10,22 @@ function makeQueryClient() { staleTime: 60 * 1000, }, }, - }) + }); } -let browserQueryClient: QueryClient | undefined = undefined +let browserQueryClient: QueryClient | undefined; function getQueryClient() { if (isServer) { - return makeQueryClient() + return makeQueryClient(); } else { - if (!browserQueryClient) browserQueryClient = makeQueryClient() - return browserQueryClient + if (!browserQueryClient) browserQueryClient = makeQueryClient(); + return browserQueryClient; } } export function ReactQueryProvider({ children }: { children: React.ReactNode }) { - const queryClient = getQueryClient() + const queryClient = getQueryClient(); - return {children} + return {children}; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/solana/solana-provider.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/solana/solana-provider.tsx index 43e29b2ba..993f29778 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/solana/solana-provider.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/solana/solana-provider.tsx @@ -1,30 +1,30 @@ -'use client' +"use client"; -import { WalletError } from '@solana/wallet-adapter-base' +import type { WalletError } from "@solana/wallet-adapter-base"; import { - AnchorWallet, + type AnchorWallet, ConnectionProvider, useConnection, useWallet, WalletProvider, -} from '@solana/wallet-adapter-react' -import { WalletModalProvider } from '@solana/wallet-adapter-react-ui' -import dynamic from 'next/dynamic' -import { ReactNode, useCallback, useMemo } from 'react' -import { useCluster } from '../cluster/cluster-data-access' -import '@solana/wallet-adapter-react-ui/styles.css' -import { AnchorProvider } from '@anchor-lang/core' +} from "@solana/wallet-adapter-react"; +import { WalletModalProvider } from "@solana/wallet-adapter-react-ui"; +import dynamic from "next/dynamic"; +import { type ReactNode, useCallback, useMemo } from "react"; +import { useCluster } from "../cluster/cluster-data-access"; +import "@solana/wallet-adapter-react-ui/styles.css"; +import { AnchorProvider } from "@anchor-lang/core"; -export const WalletButton = dynamic(async () => (await import('@solana/wallet-adapter-react-ui')).WalletMultiButton, { +export const WalletButton = dynamic(async () => (await import("@solana/wallet-adapter-react-ui")).WalletMultiButton, { ssr: false, -}) +}); export function SolanaProvider({ children }: { children: ReactNode }) { - const { cluster } = useCluster() - const endpoint = useMemo(() => cluster.endpoint, [cluster]) + const { cluster } = useCluster(); + const endpoint = useMemo(() => cluster.endpoint, [cluster]); const onError = useCallback((error: WalletError) => { - console.error(error) - }, []) + console.error(error); + }, []); return ( @@ -32,12 +32,14 @@ export function SolanaProvider({ children }: { children: ReactNode }) { {children} - ) + ); } export function useAnchorProvider() { - const { connection } = useConnection() - const wallet = useWallet() + const { connection } = useConnection(); + const wallet = useWallet(); - return new AnchorProvider(connection, wallet as AnchorWallet, { commitment: 'confirmed' }) + return new AnchorProvider(connection, wallet as AnchorWallet, { + commitment: "confirmed", + }); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/theme-provider.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/theme-provider.tsx index f7328c86a..8e41496ff 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/theme-provider.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/theme-provider.tsx @@ -1,8 +1,8 @@ -'use client' +"use client"; -import * as React from 'react' -import { ThemeProvider as NextThemesProvider } from 'next-themes' +import { ThemeProvider as NextThemesProvider } from "next-themes"; +import type * as React from "react"; export function ThemeProvider({ children, ...props }: React.ComponentProps) { - return {children} + return {children}; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/theme-select.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/theme-select.tsx index 7c8331cca..7a8617004 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/theme-select.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/theme-select.tsx @@ -1,14 +1,18 @@ -'use client' +"use client"; -import * as React from 'react' -import { Moon, Sun } from 'lucide-react' -import { useTheme } from 'next-themes' +import { Moon, Sun } from "lucide-react"; +import { useTheme } from "next-themes"; -import { Button } from '@/components/ui/button' -import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu' +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; export function ThemeSelect() { - const { setTheme } = useTheme() + const { setTheme } = useTheme(); return ( @@ -20,10 +24,10 @@ export function ThemeSelect() { - setTheme('light')}>Light - setTheme('dark')}>Dark - setTheme('system')}>System + setTheme("light")}>Light + setTheme("dark")}>Dark + setTheme("system")}>System - ) + ); } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/alert.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/alert.tsx index cbf8da2b6..174412a6c 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/alert.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/alert.tsx @@ -1,51 +1,51 @@ -import * as React from 'react' -import { cva, type VariantProps } from 'class-variance-authority' +import { cva, type VariantProps } from "class-variance-authority"; +import type * as React from "react"; -import { cn } from '@/lib/utils' +import { cn } from "@/lib/utils"; const alertVariants = cva( - 'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current', + "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", { variants: { variant: { - default: 'bg-card text-card-foreground', + default: "bg-card text-card-foreground", destructive: - 'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90', + "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90", warning: - 'text-yellow-500 bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-yellow-500/90 border-yellow-500 dark:bg-yellow-900/10', + "text-yellow-500 bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-yellow-500/90 border-yellow-500 dark:bg-yellow-900/10", }, }, defaultVariants: { - variant: 'default', + variant: "default", }, }, -) +); -function Alert({ className, variant, ...props }: React.ComponentProps<'div'> & VariantProps) { - return
    +function Alert({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps) { + return
    ; } -function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) { +function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { return (
    - ) + ); } -function AlertDescription({ className, ...props }: React.ComponentProps<'div'>) { +function AlertDescription({ className, ...props }: React.ComponentProps<"div">) { return (
    - ) + ); } -export { Alert, AlertTitle, AlertDescription } +export { Alert, AlertDescription, AlertTitle }; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/button.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/button.tsx index 43a479064..45e1107fd 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/button.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/button.tsx @@ -1,36 +1,36 @@ -import * as React from 'react' -import { Slot } from '@radix-ui/react-slot' -import { cva, type VariantProps } from 'class-variance-authority' +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; +import type * as React from "react"; -import { cn } from '@/lib/utils' +import { cn } from "@/lib/utils"; const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { - default: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90', + default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", destructive: - 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', + "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: - 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', - secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80', - ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', - link: 'text-primary underline-offset-4 hover:underline', + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", + link: "text-primary underline-offset-4 hover:underline", }, size: { - default: 'h-9 px-4 py-2 has-[>svg]:px-3', - sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5', - lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', - icon: 'size-9', + default: "h-9 px-4 py-2 has-[>svg]:px-3", + sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", + lg: "h-10 rounded-md px-6 has-[>svg]:px-4", + icon: "size-9", }, }, defaultVariants: { - variant: 'default', - size: 'default', + variant: "default", + size: "default", }, }, -) +); function Button({ className, @@ -38,13 +38,13 @@ function Button({ size, asChild = false, ...props -}: React.ComponentProps<'button'> & +}: React.ComponentProps<"button"> & VariantProps & { - asChild?: boolean + asChild?: boolean; }) { - const Comp = asChild ? Slot : 'button' + const Comp = asChild ? Slot : "button"; - return + return ; } -export { Button, buttonVariants } +export { Button, buttonVariants }; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/card.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/card.tsx index bf20394f7..e5c165f82 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/card.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/card.tsx @@ -1,54 +1,56 @@ -import * as React from 'react' +import type * as React from "react"; -import { cn } from '@/lib/utils' +import { cn } from "@/lib/utils"; -function Card({ className, ...props }: React.ComponentProps<'div'>) { +function Card({ className, ...props }: React.ComponentProps<"div">) { return (
    - ) + ); } -function CardHeader({ className, ...props }: React.ComponentProps<'div'>) { +function CardHeader({ className, ...props }: React.ComponentProps<"div">) { return (
    - ) + ); } -function CardTitle({ className, ...props }: React.ComponentProps<'div'>) { - return
    +function CardTitle({ className, ...props }: React.ComponentProps<"div">) { + return
    ; } -function CardDescription({ className, ...props }: React.ComponentProps<'div'>) { - return
    +function CardDescription({ className, ...props }: React.ComponentProps<"div">) { + return
    ; } -function CardAction({ className, ...props }: React.ComponentProps<'div'>) { +function CardAction({ className, ...props }: React.ComponentProps<"div">) { return (
    - ) + ); } -function CardContent({ className, ...props }: React.ComponentProps<'div'>) { - return
    +function CardContent({ className, ...props }: React.ComponentProps<"div">) { + return
    ; } -function CardFooter({ className, ...props }: React.ComponentProps<'div'>) { - return
    +function CardFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
    + ); } -export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent } +export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/dialog.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/dialog.tsx index f35cad9d9..4a3cb9e9b 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/dialog.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/dialog.tsx @@ -1,25 +1,25 @@ -'use client' +"use client"; -import * as React from 'react' -import * as DialogPrimitive from '@radix-ui/react-dialog' -import { XIcon } from 'lucide-react' +import * as DialogPrimitive from "@radix-ui/react-dialog"; +import { XIcon } from "lucide-react"; +import type * as React from "react"; -import { cn } from '@/lib/utils' +import { cn } from "@/lib/utils"; function Dialog({ ...props }: React.ComponentProps) { - return + return ; } function DialogTrigger({ ...props }: React.ComponentProps) { - return + return ; } function DialogPortal({ ...props }: React.ComponentProps) { - return + return ; } function DialogClose({ ...props }: React.ComponentProps) { - return + return ; } function DialogOverlay({ className, ...props }: React.ComponentProps) { @@ -27,12 +27,12 @@ function DialogOverlay({ className, ...props }: React.ComponentProps - ) + ); } function DialogContent({ className, children, ...props }: React.ComponentProps) { @@ -42,7 +42,7 @@ function DialogContent({ className, children, ...props }: React.ComponentProps - ) + ); } -function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) { +function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { return (
    - ) + ); } -function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) { +function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { return (
    - ) + ); } function DialogTitle({ className, ...props }: React.ComponentProps) { return ( - ) + ); } function DialogDescription({ className, ...props }: React.ComponentProps) { return ( - ) + ); } export { @@ -108,4 +108,4 @@ export { DialogPortal, DialogTitle, DialogTrigger, -} +}; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/dropdown-menu.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/dropdown-menu.tsx index 6c34345fb..c485a2a37 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/dropdown-menu.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/dropdown-menu.tsx @@ -1,21 +1,21 @@ -'use client' +"use client"; -import * as React from 'react' -import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu' -import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react' +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"; +import type * as React from "react"; -import { cn } from '@/lib/utils' +import { cn } from "@/lib/utils"; function DropdownMenu({ ...props }: React.ComponentProps) { - return + return ; } function DropdownMenuPortal({ ...props }: React.ComponentProps) { - return + return ; } function DropdownMenuTrigger({ ...props }: React.ComponentProps) { - return + return ; } function DropdownMenuContent({ @@ -29,27 +29,27 @@ function DropdownMenuContent({ data-slot="dropdown-menu-content" sideOffset={sideOffset} className={cn( - 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md', + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", className, )} {...props} /> - ) + ); } function DropdownMenuGroup({ ...props }: React.ComponentProps) { - return + return ; } function DropdownMenuItem({ className, inset, - variant = 'default', + variant = "default", ...props }: React.ComponentProps & { - inset?: boolean - variant?: 'default' | 'destructive' + inset?: boolean; + variant?: "default" | "destructive"; }) { return ( - ) + ); } function DropdownMenuCheckboxItem({ @@ -88,11 +88,11 @@ function DropdownMenuCheckboxItem({ {children} - ) + ); } function DropdownMenuRadioGroup({ ...props }: React.ComponentProps) { - return + return ; } function DropdownMenuRadioItem({ @@ -116,7 +116,7 @@ function DropdownMenuRadioItem({ {children} - ) + ); } function DropdownMenuLabel({ @@ -124,40 +124,40 @@ function DropdownMenuLabel({ inset, ...props }: React.ComponentProps & { - inset?: boolean + inset?: boolean; }) { return ( - ) + ); } function DropdownMenuSeparator({ className, ...props }: React.ComponentProps) { return ( - ) + ); } -function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) { +function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<"span">) { return ( - ) + ); } function DropdownMenuSub({ ...props }: React.ComponentProps) { - return + return ; } function DropdownMenuSubTrigger({ @@ -166,14 +166,14 @@ function DropdownMenuSubTrigger({ children, ...props }: React.ComponentProps & { - inset?: boolean + inset?: boolean; }) { return ( - ) + ); } function DropdownMenuSubContent({ @@ -192,28 +192,28 @@ function DropdownMenuSubContent({ - ) + ); } export { DropdownMenu, - DropdownMenuPortal, - DropdownMenuTrigger, + DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, - DropdownMenuLabel, DropdownMenuItem, - DropdownMenuCheckboxItem, + DropdownMenuLabel, + DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, - DropdownMenuSubTrigger, DropdownMenuSubContent, -} + DropdownMenuSubTrigger, + DropdownMenuTrigger, +}; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/input.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/input.tsx index 75fee7dfc..cb0e803b0 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/input.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/input.tsx @@ -1,21 +1,21 @@ -import * as React from 'react' +import type * as React from "react"; -import { cn } from '@/lib/utils' +import { cn } from "@/lib/utils"; -function Input({ className, type, ...props }: React.ComponentProps<'input'>) { +function Input({ className, type, ...props }: React.ComponentProps<"input">) { return ( - ) + ); } -export { Input } +export { Input }; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/label.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/label.tsx index a50c56949..aa7fe645a 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/label.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/label.tsx @@ -1,21 +1,21 @@ -'use client' +"use client"; -import * as React from 'react' -import * as LabelPrimitive from '@radix-ui/react-label' +import * as LabelPrimitive from "@radix-ui/react-label"; +import type * as React from "react"; -import { cn } from '@/lib/utils' +import { cn } from "@/lib/utils"; function Label({ className, ...props }: React.ComponentProps) { return ( - ) + ); } -export { Label } +export { Label }; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/sonner.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/sonner.tsx index 0626cafa8..f96a98d91 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/sonner.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/sonner.tsx @@ -1,25 +1,25 @@ -'use client' +"use client"; -import { useTheme } from 'next-themes' -import { Toaster as Sonner, ToasterProps } from 'sonner' +import { useTheme } from "next-themes"; +import { Toaster as Sonner, type ToasterProps } from "sonner"; const Toaster = ({ ...props }: ToasterProps) => { - const { theme = 'system' } = useTheme() + const { theme = "system" } = useTheme(); return ( - ) -} + ); +}; -export { Toaster } +export { Toaster }; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/table.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/table.tsx index e5351ccd0..afe6d5f82 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/table.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/ui/table.tsx @@ -1,75 +1,75 @@ -'use client' +"use client"; -import * as React from 'react' +import type * as React from "react"; -import { cn } from '@/lib/utils' +import { cn } from "@/lib/utils"; -function Table({ className, ...props }: React.ComponentProps<'table'>) { +function Table({ className, ...props }: React.ComponentProps<"table">) { return (
    - +
    - ) + ); } -function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) { - return +function TableHeader({ className, ...props }: React.ComponentProps<"thead">) { + return ; } -function TableBody({ className, ...props }: React.ComponentProps<'tbody'>) { - return +function TableBody({ className, ...props }: React.ComponentProps<"tbody">) { + return ; } -function TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) { +function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) { return ( tr]:last:border-b-0', className)} + className={cn("bg-muted/50 border-t font-medium [&>tr]:last:border-b-0", className)} {...props} /> - ) + ); } -function TableRow({ className, ...props }: React.ComponentProps<'tr'>) { +function TableRow({ className, ...props }: React.ComponentProps<"tr">) { return ( - ) + ); } -function TableHead({ className, ...props }: React.ComponentProps<'th'>) { +function TableHead({ className, ...props }: React.ComponentProps<"th">) { return (
    [role=checkbox]]:translate-y-[2px]', + "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className, )} {...props} /> - ) + ); } -function TableCell({ className, ...props }: React.ComponentProps<'td'>) { +function TableCell({ className, ...props }: React.ComponentProps<"td">) { return ( [role=checkbox]]:translate-y-[2px]', + "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className, )} {...props} /> - ) + ); } -function TableCaption({ className, ...props }: React.ComponentProps<'caption'>) { +function TableCaption({ className, ...props }: React.ComponentProps<"caption">) { return ( -
    - ) + + ); } -export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } +export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow }; diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/use-transaction-toast.tsx b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/use-transaction-toast.tsx index d354a5d17..6032f5d85 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/use-transaction-toast.tsx +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/components/use-transaction-toast.tsx @@ -1,13 +1,13 @@ -import { toast } from 'sonner' -import { ExplorerLink } from './cluster/cluster-ui' -import { Connection, SendTransactionError } from '@solana/web3.js' +import type { Connection, SendTransactionError } from "@solana/web3.js"; +import { toast } from "sonner"; +import { ExplorerLink } from "./cluster/cluster-ui"; export function useTransactionToast() { return (signature: string) => { - toast('Transaction sent', { + toast("Transaction sent", { description: , - }) - } + }); + }; } export function useTransactionErrorToast() { @@ -16,18 +16,18 @@ export function useTransactionErrorToast() { const anchorError = logs.find((l) => l.startsWith("Program log: AnchorError occurred")); if (anchorError) { if (anchorError.includes("WalletBlocked")) { - toast.error(`Destination wallet is blocked from receiving funds.`) + toast.error(`Destination wallet is blocked from receiving funds.`); } else if (anchorError.includes("WalletNotAllowed")) { - toast.error(`Destination wallet is not allowed to receive funds.`) + toast.error(`Destination wallet is not allowed to receive funds.`); } else if (anchorError.includes("AmountNotAllowed")) { - toast.error(`Destination wallet is not authorized to receive this amount.`) + toast.error(`Destination wallet is not authorized to receive this amount.`); } else { - console.log("ERROR: ", error) - toast.error(`Failed to run program: ${error}`) + console.log("ERROR: ", error); + toast.error(`Failed to run program: ${error}`); } } else { - console.log("ERROR: ", error) - toast.error(`Failed to run program: ${error}`) + console.log("ERROR: ", error); + toast.error(`Failed to run program: ${error}`); } - } + }; } diff --git a/tokens/token-2022/transfer-hook/allow-block-list-token/src/lib/utils.ts b/tokens/token-2022/transfer-hook/allow-block-list-token/src/lib/utils.ts index 1f56ee2d2..c666f4338 100644 --- a/tokens/token-2022/transfer-hook/allow-block-list-token/src/lib/utils.ts +++ b/tokens/token-2022/transfer-hook/allow-block-list-token/src/lib/utils.ts @@ -1,11 +1,11 @@ -import { type ClassValue, clsx } from 'clsx'; -import { twMerge } from 'tailwind-merge'; +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } -export function ellipsify(str = '', len = 4, delimiter = '..') { +export function ellipsify(str = "", len = 4, delimiter = "..") { const strLen = str.length; const limit = len * 2 + delimiter.length; diff --git a/tokens/token-2022/transfer-hook/counter/anchor/Anchor.toml b/tokens/token-2022/transfer-hook/counter/anchor/Anchor.toml index 3ad7e2a52..470d83f16 100644 --- a/tokens/token-2022/transfer-hook/counter/anchor/Anchor.toml +++ b/tokens/token-2022/transfer-hook/counter/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -transfer_hook = "1qahDxKHeCLZhbBU2NyMU6vQCQmEUmdeSEBrG5drffK" - -# [registry] section removed — no longer used in Anchor 1.0 +transfer_hook = "FEu8GvcwSvmeaf8hQ2SvfzSYcSNSuB32WdfYUARTcmqp" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 100000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/transfer-hook/counter/anchor/migrations/deploy.ts b/tokens/token-2022/transfer-hook/counter/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/transfer-hook/counter/anchor/migrations/deploy.ts +++ b/tokens/token-2022/transfer-hook/counter/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/transfer-hook/counter/anchor/package.json b/tokens/token-2022/transfer-hook/counter/anchor/package.json index 3c254f5f9..466b8ee71 100644 --- a/tokens/token-2022/transfer-hook/counter/anchor/package.json +++ b/tokens/token-2022/transfer-hook/counter/anchor/package.json @@ -1,24 +1,24 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.0", - "@solana/web3.js": "^1.98.4" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/chai-as-promised": "^7.1.8", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.2", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.0", + "@solana/web3.js": "^1.98.4" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/chai-as-promised": "^7.1.8", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "chai-as-promised": "^7.1.2", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/transfer-hook/counter/anchor/pnpm-lock.yaml b/tokens/token-2022/transfer-hook/counter/anchor/pnpm-lock.yaml index 17b058e96..fc594a80b 100644 --- a/tokens/token-2022/transfer-hook/counter/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/transfer-hook/counter/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) '@solana/spl-token': specifier: ^0.4.0 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@6.0.6) @@ -51,18 +51,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.29.2': @@ -797,16 +797,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 @@ -824,7 +824,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.29.2': {} diff --git a/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/Cargo.toml b/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/Cargo.toml index ff4cc96fd..841067236 100644 --- a/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/Cargo.toml +++ b/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/Cargo.toml @@ -20,12 +20,18 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" -anchor-spl = "1.0.0-rc.5" +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" spl-discriminator = "0.4.1" spl-tlv-account-resolution = "0.9.0" spl-transfer-hook-interface = "0.9.0" +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/src/lib.rs b/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/src/lib.rs index 61d6815b7..f1473fdef 100644 --- a/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/src/lib.rs +++ b/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/src/lib.rs @@ -23,7 +23,7 @@ use spl_transfer_hook_interface::instruction::{ ExecuteInstruction, InitializeExtraAccountMetaListInstruction, }; -declare_id!("1qahDxKHeCLZhbBU2NyMU6vQCQmEUmdeSEBrG5drffK"); +declare_id!("FEu8GvcwSvmeaf8hQ2SvfzSYcSNSuB32WdfYUARTcmqp"); #[error_code] pub enum TransferError { diff --git a/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/tests/test_transfer_hook_counter.rs b/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/tests/test_transfer_hook_counter.rs new file mode 100644 index 000000000..3a9219566 --- /dev/null +++ b/tokens/token-2022/transfer-hook/counter/anchor/programs/transfer-hook/tests/test_transfer_hook_counter.rs @@ -0,0 +1,154 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::Instruction, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_account, create_token_extensions_mint, + mint_tokens_to_token_extensions_account, transfer_checked_token_extensions, + MintExtension, TOKEN_EXTENSIONS_PROGRAM_ID, + }, + transfer_hook::{build_hook_accounts, get_hook_accounts_address, HookAccount}, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn associated_token_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = transfer_hook::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/transfer_hook.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_transfer_hook_counter() { + let (mut svm, program_id, payer) = setup(); + let decimals: u8 = 9; + + // PDAs + let (counter_pda, _) = Pubkey::find_program_address(&[b"counter"], &program_id); + + // Step 1: Create mint with TransferHook extension via kite + let mint = create_token_extensions_mint( + &mut svm, + &payer, + decimals, + None, + &[MintExtension::TransferHook { + program_id: program_id, + }], + ) + .unwrap(); + svm.expire_blockhash(); + + let extra_account_meta_list = + get_hook_accounts_address(&mint, &program_id); + + // Step 2: Create token accounts and mint tokens + let recipient = Keypair::new(); + let amount: u64 = 100 * 10u64.pow(decimals as u32); + + let source_ata = create_token_extensions_account( + &mut svm, + &payer.pubkey(), + &mint, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + let dest_ata = create_token_extensions_account( + &mut svm, + &recipient.pubkey(), + &mint, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + mint_tokens_to_token_extensions_account( + &mut svm, + &mint, + &source_ata, + amount, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 3: Initialize ExtraAccountMetaList (also creates counter PDA) + let init_extra_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::InitializeExtraAccountMetaList {}.data(), + transfer_hook::accounts::InitializeExtraAccountMetaList { + payer: payer.pubkey(), + extra_account_meta_list, + mint, + counter_account: counter_pda, + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + associated_token_program: associated_token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_extra_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 4: Transfer with hook (this triggers the counter increment) + let transfer_amount: u64 = 1 * 10u64.pow(decimals as u32); + let extra_accounts = build_hook_accounts( + &mint, + &program_id, + &[HookAccount { + pubkey: counter_pda, + is_signer: false, + is_writable: true, + }], + ); + transfer_checked_token_extensions( + &mut svm, + &source_ata, + &mint, + &dest_ata, + &payer, + transfer_amount, + decimals, + &extra_accounts, + ).unwrap(); + svm.expire_blockhash(); + + // Step 5: Try calling transfer_hook directly (should fail — not transferring) + let direct_hook_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::TransferHook { amount: 1 }.data(), + transfer_hook::accounts::TransferHook { + source_token: source_ata, + mint, + destination_token: dest_ata, + owner: payer.pubkey(), + extra_account_meta_list, + counter_account: counter_pda, + } + .to_account_metas(None), + ); + let result = send_transaction_from_instructions(&mut svm, vec![direct_hook_ix], &[&payer], &payer.pubkey()); + assert!( + result.is_err(), + "Calling transfer_hook directly should fail because token is not transferring" + ); +} diff --git a/tokens/token-2022/transfer-hook/counter/anchor/tests/transfer-hook.ts b/tokens/token-2022/transfer-hook/counter/anchor/tests/transfer-hook.ts index 1ace10b1a..feaced79d 100644 --- a/tokens/token-2022/transfer-hook/counter/anchor/tests/transfer-hook.ts +++ b/tokens/token-2022/transfer-hook/counter/anchor/tests/transfer-hook.ts @@ -1,5 +1,5 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; import { ASSOCIATED_TOKEN_PROGRAM_ID, createAssociatedTokenAccountInstruction, @@ -11,16 +11,23 @@ import { getAssociatedTokenAddressSync, getMintLen, TOKEN_2022_PROGRAM_ID, -} from '@solana/spl-token'; -import { Keypair, PublicKey, SendTransactionError, SystemProgram, sendAndConfirmTransaction, Transaction } from '@solana/web3.js'; -import { BN } from 'bn.js'; -import chai, { expect } from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import type { TransferHook } from '../target/types/transfer_hook'; +} from "@solana/spl-token"; +import { + Keypair, + PublicKey, + SendTransactionError, + SystemProgram, + sendAndConfirmTransaction, + Transaction, +} from "@solana/web3.js"; +import { BN } from "bn.js"; +import chai, { expect } from "chai"; +import chaiAsPromised from "chai-as-promised"; +import type { TransferHook } from "../target/types/transfer_hook"; chai.use(chaiAsPromised); -describe('transfer-hook', () => { +describe("transfer-hook", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); @@ -55,13 +62,13 @@ describe('transfer-hook', () => { // ExtraAccountMetaList address // Store extra accounts required by the custom transfer hook instruction const [extraAccountMetaListPDA] = PublicKey.findProgramAddressSync( - [Buffer.from('extra-account-metas'), mint.publicKey.toBuffer()], + [Buffer.from("extra-account-metas"), mint.publicKey.toBuffer()], program.programId, ); - const [counterPDA] = PublicKey.findProgramAddressSync([Buffer.from('counter')], program.programId); + const [counterPDA] = PublicKey.findProgramAddressSync([Buffer.from("counter")], program.programId); - it('Create Mint Account with Transfer Hook Extension', async () => { + it("Create Mint Account with Transfer Hook Extension", async () => { const extensions = [ExtensionType.TransferHook]; const mintLen = getMintLen(extensions); const lamports = await provider.connection.getMinimumBalanceForRentExemption(mintLen); @@ -85,12 +92,12 @@ describe('transfer-hook', () => { const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer, mint], { skipPreflight: true, - commitment: 'finalized', + commitment: "finalized", }); const txDetails = await program.provider.connection.getTransaction(txSig, { maxSupportedTransactionVersion: 0, - commitment: 'confirmed', + commitment: "confirmed", }); console.log(txDetails.meta.logMessages); @@ -99,7 +106,7 @@ describe('transfer-hook', () => { // Create the two token accounts for the transfer-hook enabled mint // Fund the sender token account with 100 tokens - it('Create Token Accounts and Mint Tokens', async () => { + it("Create Token Accounts and Mint Tokens", async () => { // 100 tokens const amount = 100 * 10 ** decimals; @@ -129,7 +136,7 @@ describe('transfer-hook', () => { }); // Account to store extra accounts required by the transfer hook instruction - it('Create ExtraAccountMetaList Account', async () => { + it("Create ExtraAccountMetaList Account", async () => { const initializeExtraAccountMetaListInstruction = await program.methods .initializeExtraAccountMetaList() .accounts({ @@ -139,11 +146,14 @@ describe('transfer-hook', () => { const transaction = new Transaction().add(initializeExtraAccountMetaListInstruction); - const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { skipPreflight: true, commitment: 'confirmed' }); - console.log('Transaction Signature:', txSig); + const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { + skipPreflight: true, + commitment: "confirmed", + }); + console.log("Transaction Signature:", txSig); }); - it('Transfer Hook with Extra Account Meta', async () => { + it("Transfer Hook with Extra Account Meta", async () => { // 1 tokens const amount = 1 * 10 ** decimals; const amountBigInt = BigInt(amount); @@ -157,7 +167,7 @@ describe('transfer-hook', () => { amountBigInt, decimals, [], - 'confirmed', + "confirmed", TOKEN_2022_PROGRAM_ID, ); @@ -168,10 +178,10 @@ describe('transfer-hook', () => { const transaction = new Transaction().add(transferInstructionWithHelper); const txSig = await sendAndConfirmTransaction(connection, transaction, [wallet.payer], { skipPreflight: true }); - console.log('Transfer Signature:', txSig); + console.log("Transfer Signature:", txSig); }); - it('Try call transfer hook without transfer', async () => { + it("Try call transfer hook without transfer", async () => { const transferHookIx = await program.methods .transferHook(new BN(1)) .accounts({ diff --git a/tokens/token-2022/transfer-hook/hello-world/anchor/Anchor.toml b/tokens/token-2022/transfer-hook/hello-world/anchor/Anchor.toml index 9f5b53b64..69837e950 100644 --- a/tokens/token-2022/transfer-hook/hello-world/anchor/Anchor.toml +++ b/tokens/token-2022/transfer-hook/hello-world/anchor/Anchor.toml @@ -6,18 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -transfer_hook = "jY5DfVksJT8Le38LCaQhz5USeiGu4rUeVSS8QRAMoba" - -# [registry] section removed — no longer used in Anchor 1.0 +transfer_hook = "2CnfERh8AAgu7hY5Pz6nNSjU5UihtfH8YrHAbXBoCwKg" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" -# Transfer-hook tests use the real local validator (not bankrun). -# No external program clones needed — this project doesn't use Metaplex. -# The previous [[test.validator.clone]] of metaplex was unnecessary and -# caused 5-minute timeouts in CI trying to fetch from devnet. +[hooks] diff --git a/tokens/token-2022/transfer-hook/hello-world/anchor/migrations/deploy.ts b/tokens/token-2022/transfer-hook/hello-world/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/transfer-hook/hello-world/anchor/migrations/deploy.ts +++ b/tokens/token-2022/transfer-hook/hello-world/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/transfer-hook/hello-world/anchor/package.json b/tokens/token-2022/transfer-hook/hello-world/anchor/package.json index 3c254f5f9..466b8ee71 100644 --- a/tokens/token-2022/transfer-hook/hello-world/anchor/package.json +++ b/tokens/token-2022/transfer-hook/hello-world/anchor/package.json @@ -1,24 +1,24 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.0", - "@solana/web3.js": "^1.98.4" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/chai-as-promised": "^7.1.8", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.2", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.0", + "@solana/web3.js": "^1.98.4" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/chai-as-promised": "^7.1.8", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "chai-as-promised": "^7.1.2", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/transfer-hook/hello-world/anchor/pnpm-lock.yaml b/tokens/token-2022/transfer-hook/hello-world/anchor/pnpm-lock.yaml index 17b058e96..fc594a80b 100644 --- a/tokens/token-2022/transfer-hook/hello-world/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/transfer-hook/hello-world/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) '@solana/spl-token': specifier: ^0.4.0 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@6.0.6) @@ -51,18 +51,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.29.2': @@ -797,16 +797,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@6.0.6) bn.js: 5.2.2 @@ -824,7 +824,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.29.2': {} diff --git a/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/Cargo.toml b/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/Cargo.toml index ff4cc96fd..841067236 100644 --- a/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/Cargo.toml +++ b/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/Cargo.toml @@ -20,12 +20,18 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" -anchor-spl = "1.0.0-rc.5" +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" spl-discriminator = "0.4.1" spl-tlv-account-resolution = "0.9.0" spl-transfer-hook-interface = "0.9.0" +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/src/lib.rs b/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/src/lib.rs index c036cdf5d..9a7caebe4 100644 --- a/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/src/lib.rs +++ b/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/src/lib.rs @@ -28,7 +28,7 @@ use spl_transfer_hook_interface::instruction::{ ExecuteInstruction, InitializeExtraAccountMetaListInstruction, }; -declare_id!("jY5DfVksJT8Le38LCaQhz5USeiGu4rUeVSS8QRAMoba"); +declare_id!("2CnfERh8AAgu7hY5Pz6nNSjU5UihtfH8YrHAbXBoCwKg"); #[error_code] pub enum TransferError { diff --git a/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/tests/test_transfer_hook.rs b/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/tests/test_transfer_hook.rs new file mode 100644 index 000000000..2bab7fa31 --- /dev/null +++ b/tokens/token-2022/transfer-hook/hello-world/anchor/programs/transfer-hook/tests/test_transfer_hook.rs @@ -0,0 +1,154 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::Instruction, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_account, get_token_extensions_account_address, + mint_tokens_to_token_extensions_account, transfer_checked_token_extensions, + TOKEN_EXTENSIONS_PROGRAM_ID, + }, + transfer_hook::{build_hook_accounts, get_hook_accounts_address}, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn associated_token_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = transfer_hook::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/transfer_hook.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_transfer_hook_hello_world() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + let recipient = Keypair::new(); + let ata_program = associated_token_program_id(); + let decimals: u8 = 2; + + // ExtraAccountMetaList PDA + let extra_account_meta_list = + get_hook_accounts_address(&mint_keypair.pubkey(), &program_id); + + // Step 1: Create mint with transfer hook extension pointing to our program + // (uses the program's own Initialize instruction, not kite, since it sets up + // the mint with the program as the hook authority) + let initialize_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::Initialize { + _decimals: decimals, + } + .data(), + transfer_hook::accounts::Initialize { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![initialize_ix], &[&payer, &mint_keypair], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 2: Create token accounts and mint tokens + let amount: u64 = 100 * 10u64.pow(decimals as u32); + let source_ata = create_token_extensions_account( + &mut svm, + &payer.pubkey(), + &mint_keypair.pubkey(), + &payer, + ).unwrap(); + svm.expire_blockhash(); + + let dest_ata = create_token_extensions_account( + &mut svm, + &recipient.pubkey(), + &mint_keypair.pubkey(), + &payer, + ).unwrap(); + svm.expire_blockhash(); + + mint_tokens_to_token_extensions_account( + &mut svm, + &mint_keypair.pubkey(), + &source_ata, + amount, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 3: Create ExtraAccountMetaList account + let init_extra_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::InitializeExtraAccountMetaList {}.data(), + transfer_hook::accounts::InitializeExtraAccountMetaList { + payer: payer.pubkey(), + extra_account_meta_list, + mint: mint_keypair.pubkey(), + token_program: TOKEN_EXTENSIONS_PROGRAM_ID, + associated_token_program: ata_program, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_extra_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 4: Transfer with transfer hook + let transfer_amount: u64 = 1 * 10u64.pow(decimals as u32); + let extra_accounts = build_hook_accounts( + &mint_keypair.pubkey(), + &program_id, + &[], // hello-world hook has no user-defined extra accounts + ); + transfer_checked_token_extensions( + &mut svm, + &source_ata, + &mint_keypair.pubkey(), + &dest_ata, + &payer, + transfer_amount, + decimals, + &extra_accounts, + ).unwrap(); + svm.expire_blockhash(); + + // Step 5: Try calling transfer_hook directly (should fail — not transferring) + let direct_hook_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::TransferHook { _amount: 1 }.data(), + transfer_hook::accounts::TransferHook { + source_token: source_ata, + mint: mint_keypair.pubkey(), + destination_token: dest_ata, + owner: payer.pubkey(), + extra_account_meta_list, + } + .to_account_metas(None), + ); + let result = send_transaction_from_instructions(&mut svm, vec![direct_hook_ix], &[&payer], &payer.pubkey()); + assert!( + result.is_err(), + "Calling transfer_hook directly should fail because token is not transferring" + ); +} diff --git a/tokens/token-2022/transfer-hook/hello-world/anchor/tests/transfer-hook.ts b/tokens/token-2022/transfer-hook/hello-world/anchor/tests/transfer-hook.ts index 7f1dd1825..03716a2b4 100644 --- a/tokens/token-2022/transfer-hook/hello-world/anchor/tests/transfer-hook.ts +++ b/tokens/token-2022/transfer-hook/hello-world/anchor/tests/transfer-hook.ts @@ -1,5 +1,5 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; import { ASSOCIATED_TOKEN_PROGRAM_ID, createAssociatedTokenAccountInstruction, @@ -7,16 +7,16 @@ import { createTransferCheckedWithTransferHookInstruction, getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, -} from '@solana/spl-token'; -import { Keypair, SendTransactionError, sendAndConfirmTransaction, Transaction } from '@solana/web3.js'; -import { BN } from 'bn.js'; -import chai, { expect } from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import type { TransferHook } from '../target/types/transfer_hook'; +} from "@solana/spl-token"; +import { Keypair, SendTransactionError, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; +import { BN } from "bn.js"; +import chai, { expect } from "chai"; +import chaiAsPromised from "chai-as-promised"; +import type { TransferHook } from "../target/types/transfer_hook"; chai.use(chaiAsPromised); -describe('transfer-hook', () => { +describe("transfer-hook", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); @@ -48,18 +48,18 @@ describe('transfer-hook', () => { ASSOCIATED_TOKEN_PROGRAM_ID, ); - it('Create Mint with Transfer Hook Extension', async () => { + it("Create Mint with Transfer Hook Extension", async () => { const transactionSignature = await program.methods .initialize(decimals) .accounts({ mintAccount: mint.publicKey }) .signers([mint]) .rpc({ skipPreflight: true }); - console.log('Your transaction signature', transactionSignature); + console.log("Your transaction signature", transactionSignature); }); // Create the two token accounts for the transfer-hook enabled mint // Fund the sender token account with 100 tokens - it('Create Token Accounts and Mint Tokens', async () => { + it("Create Token Accounts and Mint Tokens", async () => { // 100 tokens const amount = 100 * 10 ** decimals; @@ -89,7 +89,7 @@ describe('transfer-hook', () => { }); // Account to store extra accounts required by the transfer hook instruction - it('Create ExtraAccountMetaList Account', async () => { + it("Create ExtraAccountMetaList Account", async () => { const initializeExtraAccountMetaListInstruction = await program.methods .initializeExtraAccountMetaList() .accounts({ @@ -99,11 +99,14 @@ describe('transfer-hook', () => { const transaction = new Transaction().add(initializeExtraAccountMetaListInstruction); - const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { skipPreflight: true, commitment: 'confirmed' }); - console.log('Transaction Signature:', txSig); + const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { + skipPreflight: true, + commitment: "confirmed", + }); + console.log("Transaction Signature:", txSig); }); - it('Transfer Hook with Extra Account Meta', async () => { + it("Transfer Hook with Extra Account Meta", async () => { // 1 tokens const amount = 1 * 10 ** decimals; const bigIntAmount = BigInt(amount); @@ -118,17 +121,17 @@ describe('transfer-hook', () => { bigIntAmount, decimals, [], - 'confirmed', + "confirmed", TOKEN_2022_PROGRAM_ID, ); const transaction = new Transaction().add(transferInstruction); const txSig = await sendAndConfirmTransaction(connection, transaction, [wallet.payer], { skipPreflight: true }); - console.log('Transfer Signature:', txSig); + console.log("Transfer Signature:", txSig); }); - it('Try call transfer hook without transfer', async () => { + it("Try call transfer hook without transfer", async () => { const transferHookIx = await program.methods .transferHook(new BN(1)) .accounts({ diff --git a/tokens/token-2022/transfer-hook/pblock-list/codama.ts b/tokens/token-2022/transfer-hook/pblock-list/codama.ts index b21a0112c..643c667a5 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/codama.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/codama.ts @@ -1,6 +1,6 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import { renderJavaScriptVisitor, renderRustVisitor } from '@codama/renderers'; +import fs from "node:fs"; +import path from "node:path"; +import { renderJavaScriptVisitor, renderRustVisitor } from "@codama/renderers"; import { accountNode, booleanTypeNode, @@ -24,242 +24,248 @@ import { structFieldTypeNode, structTypeNode, variablePdaSeedNode, -} from 'codama'; +} from "codama"; -const _rustClientsDir = path.join(__dirname, '..', 'sdk', 'rust'); -const typescriptClientsDir = path.join(__dirname, '..', 'sdk', 'ts'); +const _rustClientsDir = path.join(__dirname, "..", "sdk", "rust"); +const typescriptClientsDir = path.join(__dirname, "..", "sdk", "ts"); const root = rootNode( programNode({ - name: 'block-list', - publicKey: 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf', - version: '1.0.0', + name: "block-list", + publicKey: "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf", + version: "1.0.0", accounts: [ accountNode({ - name: 'config', - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0)))], + name: "config", + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0)))], size: 41, - pda: pdaLinkNode('config'), - docs: ['The config PDA account'], + pda: pdaLinkNode("config"), + docs: ["The config PDA account"], data: structTypeNode([ structFieldTypeNode({ - name: 'discriminator', - type: numberTypeNode('u8'), - defaultValueStrategy: 'omitted', + name: "discriminator", + type: numberTypeNode("u8"), + defaultValueStrategy: "omitted", }), structFieldTypeNode({ - name: 'authority', + name: "authority", type: publicKeyTypeNode(), }), structFieldTypeNode({ - name: 'blocked_wallets_count', - type: numberTypeNode('u64'), + name: "blocked_wallets_count", + type: numberTypeNode("u64"), }), ]), }), accountNode({ - name: 'walletBlock', - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(1)))], + name: "walletBlock", + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(1)))], size: 33, - pda: pdaLinkNode('walletBlock'), - docs: ['The config PDA account'], + pda: pdaLinkNode("walletBlock"), + docs: ["The config PDA account"], data: structTypeNode([ structFieldTypeNode({ - name: 'authority', + name: "authority", type: publicKeyTypeNode(), }), ]), }), accountNode({ - name: 'extraMetas', - pda: pdaLinkNode('extraMetas'), - docs: ['The extra metas PDA account'], + name: "extraMetas", + pda: pdaLinkNode("extraMetas"), + docs: ["The extra metas PDA account"], }), ], instructions: [ instructionNode({ - name: 'init', + name: "init", arguments: [ instructionArgumentNode({ - name: 'discriminator', - type: numberTypeNode('u8'), + name: "discriminator", + type: numberTypeNode("u8"), defaultValue: numberValueNode(0xf1), - defaultValueStrategy: 'omitted', + defaultValueStrategy: "omitted", }), ], accounts: [ instructionAccountNode({ - name: 'authority', + name: "authority", isSigner: true, isWritable: true, }), instructionAccountNode({ - name: 'config', + name: "config", isSigner: false, isWritable: true, - defaultValue: pdaValueNode(pdaLinkNode('config')), + defaultValue: pdaValueNode(pdaLinkNode("config")), }), instructionAccountNode({ - name: 'systemProgram', - defaultValue: publicKeyValueNode('11111111111111111111111111111111', 'systemProgram'), + name: "systemProgram", + defaultValue: publicKeyValueNode("11111111111111111111111111111111", "systemProgram"), isSigner: false, isWritable: false, }), ], - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0xf1)))], - docs: ['Initialize the config PDA account'], + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0xf1)))], + docs: ["Initialize the config PDA account"], }), instructionNode({ - name: 'blockWallet', + name: "blockWallet", arguments: [ instructionArgumentNode({ - name: 'discriminator', - type: numberTypeNode('u8'), + name: "discriminator", + type: numberTypeNode("u8"), defaultValue: numberValueNode(0xf2), - defaultValueStrategy: 'omitted', + defaultValueStrategy: "omitted", }), ], accounts: [ instructionAccountNode({ - name: 'authority', + name: "authority", isSigner: true, isWritable: true, }), instructionAccountNode({ - name: 'config', + name: "config", isSigner: false, isWritable: true, - defaultValue: pdaValueNode(pdaLinkNode('config')), + defaultValue: pdaValueNode(pdaLinkNode("config")), }), instructionAccountNode({ - name: 'wallet', + name: "wallet", isSigner: false, isWritable: false, }), instructionAccountNode({ - name: 'walletBlock', + name: "walletBlock", isSigner: false, isWritable: true, }), instructionAccountNode({ - name: 'systemProgram', - defaultValue: publicKeyValueNode('11111111111111111111111111111111', 'systemProgram'), + name: "systemProgram", + defaultValue: publicKeyValueNode("11111111111111111111111111111111", "systemProgram"), isSigner: false, isWritable: false, }), ], - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0xf2)))], - docs: ['Block a wallet'], + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0xf2)))], + docs: ["Block a wallet"], }), instructionNode({ - name: 'unblockWallet', + name: "unblockWallet", arguments: [ instructionArgumentNode({ - name: 'discriminator', - type: numberTypeNode('u8'), + name: "discriminator", + type: numberTypeNode("u8"), defaultValue: numberValueNode(0xf3), - defaultValueStrategy: 'omitted', + defaultValueStrategy: "omitted", }), ], accounts: [ instructionAccountNode({ - name: 'authority', + name: "authority", isSigner: true, isWritable: true, }), instructionAccountNode({ - name: 'config', + name: "config", isSigner: false, isWritable: true, - defaultValue: pdaValueNode(pdaLinkNode('config')), + defaultValue: pdaValueNode(pdaLinkNode("config")), }), instructionAccountNode({ - name: 'walletBlock', + name: "walletBlock", isSigner: false, isWritable: true, }), instructionAccountNode({ - name: 'systemProgram', - defaultValue: publicKeyValueNode('11111111111111111111111111111111', 'systemProgram'), + name: "systemProgram", + defaultValue: publicKeyValueNode("11111111111111111111111111111111", "systemProgram"), isSigner: false, isWritable: false, }), ], - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0xf3)))], - docs: ['Unblock a wallet'], + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0xf3)))], + docs: ["Unblock a wallet"], }), instructionNode({ - name: 'setupExtraMetas', + name: "setupExtraMetas", arguments: [ instructionArgumentNode({ - name: 'discriminator', - type: numberTypeNode('u8'), + name: "discriminator", + type: numberTypeNode("u8"), defaultValue: numberValueNode(0x6a), - defaultValueStrategy: 'omitted', + defaultValueStrategy: "omitted", }), instructionArgumentNode({ - name: 'checkBothWallets', + name: "checkBothWallets", type: booleanTypeNode(), defaultValue: booleanValueNode(false), - defaultValueStrategy: 'optional', + defaultValueStrategy: "optional", }), ], accounts: [ instructionAccountNode({ - name: 'authority', + name: "authority", isSigner: true, isWritable: true, }), instructionAccountNode({ - name: 'config', + name: "config", isSigner: false, isWritable: false, - defaultValue: pdaValueNode(pdaLinkNode('config')), + defaultValue: pdaValueNode(pdaLinkNode("config")), }), instructionAccountNode({ - name: 'mint', + name: "mint", isSigner: false, isWritable: false, }), instructionAccountNode({ - name: 'extraMetas', + name: "extraMetas", isSigner: false, isWritable: true, - defaultValue: pdaValueNode(pdaLinkNode('extraMetas')), + defaultValue: pdaValueNode(pdaLinkNode("extraMetas")), }), instructionAccountNode({ - name: 'systemProgram', - defaultValue: publicKeyValueNode('11111111111111111111111111111111', 'systemProgram'), + name: "systemProgram", + defaultValue: publicKeyValueNode("11111111111111111111111111111111", "systemProgram"), isSigner: false, isWritable: false, }), ], - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0x6a)))], - docs: ['Unblock a wallet'], + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0x6a)))], + docs: ["Unblock a wallet"], }), ], pdas: [ pdaNode({ - name: 'config', - seeds: [constantPdaSeedNodeFromString('utf8', 'config')], - docs: ['The config PDA account'], + name: "config", + seeds: [constantPdaSeedNodeFromString("utf8", "config")], + docs: ["The config PDA account"], }), pdaNode({ - name: 'walletBlock', - seeds: [constantPdaSeedNodeFromString('utf8', 'wallet_block'), variablePdaSeedNode('wallet', publicKeyTypeNode())], - docs: ['The wallet block PDA account'], + name: "walletBlock", + seeds: [ + constantPdaSeedNodeFromString("utf8", "wallet_block"), + variablePdaSeedNode("wallet", publicKeyTypeNode()), + ], + docs: ["The wallet block PDA account"], }), pdaNode({ - name: 'extraMetas', - seeds: [constantPdaSeedNodeFromString('utf8', 'extra-account-metas'), variablePdaSeedNode('mint', publicKeyTypeNode())], - docs: ['The extra metas PDA account'], + name: "extraMetas", + seeds: [ + constantPdaSeedNodeFromString("utf8", "extra-account-metas"), + variablePdaSeedNode("mint", publicKeyTypeNode()), + ], + docs: ["The extra metas PDA account"], }), ], }), ); function preserveConfigFiles() { - const filesToPreserve = ['package.json', 'tsconfig.json', '.npmignore', 'pnpm-lock.yaml', 'Cargo.toml']; + const filesToPreserve = ["package.json", "tsconfig.json", ".npmignore", "pnpm-lock.yaml", "Cargo.toml"]; const preservedFiles = new Map(); for (const filename of filesToPreserve) { @@ -289,5 +295,10 @@ const codama = createFromRoot(root); const _configPreserver = preserveConfigFiles(); -codama.accept(renderJavaScriptVisitor('sdk/ts/src', { formatCode: true })); -codama.accept(renderRustVisitor('sdk/rust/src/client', { crateFolder: 'sdk/rust/', formatCode: true })); +codama.accept(renderJavaScriptVisitor("sdk/ts/src", { formatCode: true })); +codama.accept( + renderRustVisitor("sdk/rust/src/client", { + crateFolder: "sdk/rust/", + formatCode: true, + }), +); diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/codama.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/codama.ts index b21a0112c..643c667a5 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/codama.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/codama.ts @@ -1,6 +1,6 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import { renderJavaScriptVisitor, renderRustVisitor } from '@codama/renderers'; +import fs from "node:fs"; +import path from "node:path"; +import { renderJavaScriptVisitor, renderRustVisitor } from "@codama/renderers"; import { accountNode, booleanTypeNode, @@ -24,242 +24,248 @@ import { structFieldTypeNode, structTypeNode, variablePdaSeedNode, -} from 'codama'; +} from "codama"; -const _rustClientsDir = path.join(__dirname, '..', 'sdk', 'rust'); -const typescriptClientsDir = path.join(__dirname, '..', 'sdk', 'ts'); +const _rustClientsDir = path.join(__dirname, "..", "sdk", "rust"); +const typescriptClientsDir = path.join(__dirname, "..", "sdk", "ts"); const root = rootNode( programNode({ - name: 'block-list', - publicKey: 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf', - version: '1.0.0', + name: "block-list", + publicKey: "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf", + version: "1.0.0", accounts: [ accountNode({ - name: 'config', - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0)))], + name: "config", + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0)))], size: 41, - pda: pdaLinkNode('config'), - docs: ['The config PDA account'], + pda: pdaLinkNode("config"), + docs: ["The config PDA account"], data: structTypeNode([ structFieldTypeNode({ - name: 'discriminator', - type: numberTypeNode('u8'), - defaultValueStrategy: 'omitted', + name: "discriminator", + type: numberTypeNode("u8"), + defaultValueStrategy: "omitted", }), structFieldTypeNode({ - name: 'authority', + name: "authority", type: publicKeyTypeNode(), }), structFieldTypeNode({ - name: 'blocked_wallets_count', - type: numberTypeNode('u64'), + name: "blocked_wallets_count", + type: numberTypeNode("u64"), }), ]), }), accountNode({ - name: 'walletBlock', - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(1)))], + name: "walletBlock", + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(1)))], size: 33, - pda: pdaLinkNode('walletBlock'), - docs: ['The config PDA account'], + pda: pdaLinkNode("walletBlock"), + docs: ["The config PDA account"], data: structTypeNode([ structFieldTypeNode({ - name: 'authority', + name: "authority", type: publicKeyTypeNode(), }), ]), }), accountNode({ - name: 'extraMetas', - pda: pdaLinkNode('extraMetas'), - docs: ['The extra metas PDA account'], + name: "extraMetas", + pda: pdaLinkNode("extraMetas"), + docs: ["The extra metas PDA account"], }), ], instructions: [ instructionNode({ - name: 'init', + name: "init", arguments: [ instructionArgumentNode({ - name: 'discriminator', - type: numberTypeNode('u8'), + name: "discriminator", + type: numberTypeNode("u8"), defaultValue: numberValueNode(0xf1), - defaultValueStrategy: 'omitted', + defaultValueStrategy: "omitted", }), ], accounts: [ instructionAccountNode({ - name: 'authority', + name: "authority", isSigner: true, isWritable: true, }), instructionAccountNode({ - name: 'config', + name: "config", isSigner: false, isWritable: true, - defaultValue: pdaValueNode(pdaLinkNode('config')), + defaultValue: pdaValueNode(pdaLinkNode("config")), }), instructionAccountNode({ - name: 'systemProgram', - defaultValue: publicKeyValueNode('11111111111111111111111111111111', 'systemProgram'), + name: "systemProgram", + defaultValue: publicKeyValueNode("11111111111111111111111111111111", "systemProgram"), isSigner: false, isWritable: false, }), ], - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0xf1)))], - docs: ['Initialize the config PDA account'], + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0xf1)))], + docs: ["Initialize the config PDA account"], }), instructionNode({ - name: 'blockWallet', + name: "blockWallet", arguments: [ instructionArgumentNode({ - name: 'discriminator', - type: numberTypeNode('u8'), + name: "discriminator", + type: numberTypeNode("u8"), defaultValue: numberValueNode(0xf2), - defaultValueStrategy: 'omitted', + defaultValueStrategy: "omitted", }), ], accounts: [ instructionAccountNode({ - name: 'authority', + name: "authority", isSigner: true, isWritable: true, }), instructionAccountNode({ - name: 'config', + name: "config", isSigner: false, isWritable: true, - defaultValue: pdaValueNode(pdaLinkNode('config')), + defaultValue: pdaValueNode(pdaLinkNode("config")), }), instructionAccountNode({ - name: 'wallet', + name: "wallet", isSigner: false, isWritable: false, }), instructionAccountNode({ - name: 'walletBlock', + name: "walletBlock", isSigner: false, isWritable: true, }), instructionAccountNode({ - name: 'systemProgram', - defaultValue: publicKeyValueNode('11111111111111111111111111111111', 'systemProgram'), + name: "systemProgram", + defaultValue: publicKeyValueNode("11111111111111111111111111111111", "systemProgram"), isSigner: false, isWritable: false, }), ], - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0xf2)))], - docs: ['Block a wallet'], + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0xf2)))], + docs: ["Block a wallet"], }), instructionNode({ - name: 'unblockWallet', + name: "unblockWallet", arguments: [ instructionArgumentNode({ - name: 'discriminator', - type: numberTypeNode('u8'), + name: "discriminator", + type: numberTypeNode("u8"), defaultValue: numberValueNode(0xf3), - defaultValueStrategy: 'omitted', + defaultValueStrategy: "omitted", }), ], accounts: [ instructionAccountNode({ - name: 'authority', + name: "authority", isSigner: true, isWritable: true, }), instructionAccountNode({ - name: 'config', + name: "config", isSigner: false, isWritable: true, - defaultValue: pdaValueNode(pdaLinkNode('config')), + defaultValue: pdaValueNode(pdaLinkNode("config")), }), instructionAccountNode({ - name: 'walletBlock', + name: "walletBlock", isSigner: false, isWritable: true, }), instructionAccountNode({ - name: 'systemProgram', - defaultValue: publicKeyValueNode('11111111111111111111111111111111', 'systemProgram'), + name: "systemProgram", + defaultValue: publicKeyValueNode("11111111111111111111111111111111", "systemProgram"), isSigner: false, isWritable: false, }), ], - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0xf3)))], - docs: ['Unblock a wallet'], + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0xf3)))], + docs: ["Unblock a wallet"], }), instructionNode({ - name: 'setupExtraMetas', + name: "setupExtraMetas", arguments: [ instructionArgumentNode({ - name: 'discriminator', - type: numberTypeNode('u8'), + name: "discriminator", + type: numberTypeNode("u8"), defaultValue: numberValueNode(0x6a), - defaultValueStrategy: 'omitted', + defaultValueStrategy: "omitted", }), instructionArgumentNode({ - name: 'checkBothWallets', + name: "checkBothWallets", type: booleanTypeNode(), defaultValue: booleanValueNode(false), - defaultValueStrategy: 'optional', + defaultValueStrategy: "optional", }), ], accounts: [ instructionAccountNode({ - name: 'authority', + name: "authority", isSigner: true, isWritable: true, }), instructionAccountNode({ - name: 'config', + name: "config", isSigner: false, isWritable: false, - defaultValue: pdaValueNode(pdaLinkNode('config')), + defaultValue: pdaValueNode(pdaLinkNode("config")), }), instructionAccountNode({ - name: 'mint', + name: "mint", isSigner: false, isWritable: false, }), instructionAccountNode({ - name: 'extraMetas', + name: "extraMetas", isSigner: false, isWritable: true, - defaultValue: pdaValueNode(pdaLinkNode('extraMetas')), + defaultValue: pdaValueNode(pdaLinkNode("extraMetas")), }), instructionAccountNode({ - name: 'systemProgram', - defaultValue: publicKeyValueNode('11111111111111111111111111111111', 'systemProgram'), + name: "systemProgram", + defaultValue: publicKeyValueNode("11111111111111111111111111111111", "systemProgram"), isSigner: false, isWritable: false, }), ], - discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode('u8'), numberValueNode(0x6a)))], - docs: ['Unblock a wallet'], + discriminators: [constantDiscriminatorNode(constantValueNode(numberTypeNode("u8"), numberValueNode(0x6a)))], + docs: ["Unblock a wallet"], }), ], pdas: [ pdaNode({ - name: 'config', - seeds: [constantPdaSeedNodeFromString('utf8', 'config')], - docs: ['The config PDA account'], + name: "config", + seeds: [constantPdaSeedNodeFromString("utf8", "config")], + docs: ["The config PDA account"], }), pdaNode({ - name: 'walletBlock', - seeds: [constantPdaSeedNodeFromString('utf8', 'wallet_block'), variablePdaSeedNode('wallet', publicKeyTypeNode())], - docs: ['The wallet block PDA account'], + name: "walletBlock", + seeds: [ + constantPdaSeedNodeFromString("utf8", "wallet_block"), + variablePdaSeedNode("wallet", publicKeyTypeNode()), + ], + docs: ["The wallet block PDA account"], }), pdaNode({ - name: 'extraMetas', - seeds: [constantPdaSeedNodeFromString('utf8', 'extra-account-metas'), variablePdaSeedNode('mint', publicKeyTypeNode())], - docs: ['The extra metas PDA account'], + name: "extraMetas", + seeds: [ + constantPdaSeedNodeFromString("utf8", "extra-account-metas"), + variablePdaSeedNode("mint", publicKeyTypeNode()), + ], + docs: ["The extra metas PDA account"], }), ], }), ); function preserveConfigFiles() { - const filesToPreserve = ['package.json', 'tsconfig.json', '.npmignore', 'pnpm-lock.yaml', 'Cargo.toml']; + const filesToPreserve = ["package.json", "tsconfig.json", ".npmignore", "pnpm-lock.yaml", "Cargo.toml"]; const preservedFiles = new Map(); for (const filename of filesToPreserve) { @@ -289,5 +295,10 @@ const codama = createFromRoot(root); const _configPreserver = preserveConfigFiles(); -codama.accept(renderJavaScriptVisitor('sdk/ts/src', { formatCode: true })); -codama.accept(renderRustVisitor('sdk/rust/src/client', { crateFolder: 'sdk/rust/', formatCode: true })); +codama.accept(renderJavaScriptVisitor("sdk/ts/src", { formatCode: true })); +codama.accept( + renderRustVisitor("sdk/rust/src/client", { + crateFolder: "sdk/rust/", + formatCode: true, + }), +); diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/config.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/config.ts index d59757590..03a52b664 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/config.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/config.ts @@ -31,8 +31,8 @@ import { getU64Encoder, type MaybeAccount, type MaybeEncodedAccount, -} from '@solana/kit'; -import { findConfigPda } from '../pdas'; +} from "@solana/kit"; +import { findConfigPda } from "../pdas"; export const CONFIG_DISCRIMINATOR = 0; @@ -54,17 +54,17 @@ export type ConfigArgs = { export function getConfigEncoder(): Encoder { return getStructEncoder([ - ['discriminator', getU8Encoder()], - ['authority', getAddressEncoder()], - ['blockedWalletsCount', getU64Encoder()], + ["discriminator", getU8Encoder()], + ["authority", getAddressEncoder()], + ["blockedWalletsCount", getU64Encoder()], ]); } export function getConfigDecoder(): Decoder { return getStructDecoder([ - ['discriminator', getU8Decoder()], - ['authority', getAddressDecoder()], - ['blockedWalletsCount', getU64Decoder()], + ["discriminator", getU8Decoder()], + ["authority", getAddressDecoder()], + ["blockedWalletsCount", getU64Decoder()], ]); } @@ -72,8 +72,12 @@ export function getConfigCodec(): Codec { return combineCodec(getConfigEncoder(), getConfigDecoder()); } -export function decodeConfig(encodedAccount: EncodedAccount): Account; -export function decodeConfig(encodedAccount: MaybeEncodedAccount): MaybeAccount; +export function decodeConfig( + encodedAccount: EncodedAccount, +): Account; +export function decodeConfig( + encodedAccount: MaybeEncodedAccount, +): MaybeAccount; export function decodeConfig( encodedAccount: EncodedAccount | MaybeEncodedAccount, ): Account | MaybeAccount { diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/extraMetas.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/extraMetas.ts index 3292ead79..93859232f 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/extraMetas.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/extraMetas.ts @@ -25,10 +25,10 @@ import { getStructEncoder, type MaybeAccount, type MaybeEncodedAccount, -} from '@solana/kit'; -import { ExtraMetasSeeds, findExtraMetasPda } from '../pdas'; +} from "@solana/kit"; +import { type ExtraMetasSeeds, findExtraMetasPda } from "../pdas"; -export type ExtraMetas = {}; +export type ExtraMetas = Record; export type ExtraMetasArgs = ExtraMetas; @@ -44,8 +44,12 @@ export function getExtraMetasCodec(): Codec { return combineCodec(getExtraMetasEncoder(), getExtraMetasDecoder()); } -export function decodeExtraMetas(encodedAccount: EncodedAccount): Account; -export function decodeExtraMetas(encodedAccount: MaybeEncodedAccount): MaybeAccount; +export function decodeExtraMetas( + encodedAccount: EncodedAccount, +): Account; +export function decodeExtraMetas( + encodedAccount: MaybeEncodedAccount, +): MaybeAccount; export function decodeExtraMetas( encodedAccount: EncodedAccount | MaybeEncodedAccount, ): Account | MaybeAccount { diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/index.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/index.ts index ed620eb19..6135b7a67 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/index.ts @@ -6,6 +6,6 @@ * @see https://github.com/codama-idl/codama */ -export * from './config'; -export * from './extraMetas'; -export * from './walletBlock'; +export * from "./config"; +export * from "./extraMetas"; +export * from "./walletBlock"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/walletBlock.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/walletBlock.ts index 886a73f79..29a8309a9 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/walletBlock.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/accounts/walletBlock.ts @@ -28,8 +28,8 @@ import { getU8Encoder, type MaybeAccount, type MaybeEncodedAccount, -} from '@solana/kit'; -import { findWalletBlockPda, WalletBlockSeeds } from '../pdas'; +} from "@solana/kit"; +import { findWalletBlockPda, type WalletBlockSeeds } from "../pdas"; export const WALLET_BLOCK_DISCRIMINATOR = 1; @@ -42,18 +42,20 @@ export type WalletBlock = { authority: Address }; export type WalletBlockArgs = WalletBlock; export function getWalletBlockEncoder(): Encoder { - return getStructEncoder([['authority', getAddressEncoder()]]); + return getStructEncoder([["authority", getAddressEncoder()]]); } export function getWalletBlockDecoder(): Decoder { - return getStructDecoder([['authority', getAddressDecoder()]]); + return getStructDecoder([["authority", getAddressDecoder()]]); } export function getWalletBlockCodec(): Codec { return combineCodec(getWalletBlockEncoder(), getWalletBlockDecoder()); } -export function decodeWalletBlock(encodedAccount: EncodedAccount): Account; +export function decodeWalletBlock( + encodedAccount: EncodedAccount, +): Account; export function decodeWalletBlock( encodedAccount: MaybeEncodedAccount, ): MaybeAccount; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/index.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/index.ts index 1002b8203..cf9bea234 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/index.ts @@ -6,7 +6,7 @@ * @see https://github.com/codama-idl/codama */ -export * from './accounts'; -export * from './instructions'; -export * from './pdas'; -export * from './programs'; +export * from "./accounts"; +export * from "./instructions"; +export * from "./pdas"; +export * from "./programs"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/blockWallet.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/blockWallet.ts index b0f1d4d19..e49ba63b7 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/blockWallet.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/blockWallet.ts @@ -26,10 +26,10 @@ import { transformEncoder, type WritableAccount, type WritableSignerAccount, -} from '@solana/kit'; -import { findConfigPda } from '../pdas'; -import { BLOCK_LIST_PROGRAM_ADDRESS } from '../programs'; -import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +} from "@solana/kit"; +import { findConfigPda } from "../pdas"; +import { BLOCK_LIST_PROGRAM_ADDRESS } from "../programs"; +import { getAccountMetaFactory, type ResolvedAccount } from "../shared"; export const BLOCK_WALLET_DISCRIMINATOR = 242; @@ -43,13 +43,15 @@ export type BlockWalletInstruction< TAccountConfig extends string | IAccountMeta = string, TAccountWallet extends string | IAccountMeta = string, TAccountWalletBlock extends string | IAccountMeta = string, - TAccountSystemProgram extends string | IAccountMeta = '11111111111111111111111111111111', + TAccountSystemProgram extends string | IAccountMeta = "11111111111111111111111111111111", TRemainingAccounts extends readonly IAccountMeta[] = [], > = IInstruction & IInstructionWithData & IInstructionWithAccounts< [ - TAccountAuthority extends string ? WritableSignerAccount & IAccountSignerMeta : TAccountAuthority, + TAccountAuthority extends string + ? WritableSignerAccount & IAccountSignerMeta + : TAccountAuthority, TAccountConfig extends string ? WritableAccount : TAccountConfig, TAccountWallet extends string ? ReadonlyAccount : TAccountWallet, TAccountWalletBlock extends string ? WritableAccount : TAccountWalletBlock, @@ -60,17 +62,23 @@ export type BlockWalletInstruction< export type BlockWalletInstructionData = { discriminator: number }; -export type BlockWalletInstructionDataArgs = {}; +export type BlockWalletInstructionDataArgs = Record; export function getBlockWalletInstructionDataEncoder(): Encoder { - return transformEncoder(getStructEncoder([['discriminator', getU8Encoder()]]), (value) => ({ ...value, discriminator: 242 })); + return transformEncoder(getStructEncoder([["discriminator", getU8Encoder()]]), (value) => ({ + ...value, + discriminator: 242, + })); } export function getBlockWalletInstructionDataDecoder(): Decoder { - return getStructDecoder([['discriminator', getU8Decoder()]]); + return getStructDecoder([["discriminator", getU8Decoder()]]); } -export function getBlockWalletInstructionDataCodec(): Codec { +export function getBlockWalletInstructionDataCodec(): Codec< + BlockWalletInstructionDataArgs, + BlockWalletInstructionData +> { return combineCodec(getBlockWalletInstructionDataEncoder(), getBlockWalletInstructionDataDecoder()); } @@ -96,9 +104,24 @@ export async function getBlockWalletInstructionAsync< TAccountSystemProgram extends string, TProgramAddress extends Address = typeof BLOCK_LIST_PROGRAM_ADDRESS, >( - input: BlockWalletAsyncInput, + input: BlockWalletAsyncInput< + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + >, config?: { programAddress?: TProgramAddress }, -): Promise> { +): Promise< + BlockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + > +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -117,10 +140,10 @@ export async function getBlockWalletInstructionAsync< accounts.config.value = await findConfigPda(); } if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -131,7 +154,14 @@ export async function getBlockWalletInstructionAsync< ], programAddress, data: getBlockWalletInstructionDataEncoder().encode({}), - } as BlockWalletInstruction; + } as BlockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + >; return instruction; } @@ -158,9 +188,22 @@ export function getBlockWalletInstruction< TAccountSystemProgram extends string, TProgramAddress extends Address = typeof BLOCK_LIST_PROGRAM_ADDRESS, >( - input: BlockWalletInput, + input: BlockWalletInput< + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + >, config?: { programAddress?: TProgramAddress }, -): BlockWalletInstruction { +): BlockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -176,10 +219,10 @@ export function getBlockWalletInstruction< // Resolve default values. if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -190,7 +233,14 @@ export function getBlockWalletInstruction< ], programAddress, data: getBlockWalletInstructionDataEncoder().encode({}), - } as BlockWalletInstruction; + } as BlockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + >; return instruction; } @@ -215,11 +265,11 @@ export function parseBlockWalletInstruction { if (instruction.accounts.length < 5) { // TODO: Coded error. - throw new Error('Not enough accounts'); + throw new Error("Not enough accounts"); } let accountIndex = 0; const getNextAccount = () => { - const accountMeta = instruction.accounts?.[accountIndex]!; + const accountMeta = instruction.accounts[accountIndex]; accountIndex += 1; return accountMeta; }; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/index.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/index.ts index 864cb10b3..f4bba88c5 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/index.ts @@ -6,7 +6,7 @@ * @see https://github.com/codama-idl/codama */ -export * from './blockWallet'; -export * from './init'; -export * from './setupExtraMetas'; -export * from './unblockWallet'; +export * from "./blockWallet"; +export * from "./init"; +export * from "./setupExtraMetas"; +export * from "./unblockWallet"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/init.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/init.ts index f02a8fe63..860840983 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/init.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/init.ts @@ -26,10 +26,10 @@ import { transformEncoder, type WritableAccount, type WritableSignerAccount, -} from '@solana/kit'; -import { findConfigPda } from '../pdas'; -import { BLOCK_LIST_PROGRAM_ADDRESS } from '../programs'; -import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +} from "@solana/kit"; +import { findConfigPda } from "../pdas"; +import { BLOCK_LIST_PROGRAM_ADDRESS } from "../programs"; +import { getAccountMetaFactory, type ResolvedAccount } from "../shared"; export const INIT_DISCRIMINATOR = 241; @@ -41,13 +41,15 @@ export type InitInstruction< TProgram extends string = typeof BLOCK_LIST_PROGRAM_ADDRESS, TAccountAuthority extends string | IAccountMeta = string, TAccountConfig extends string | IAccountMeta = string, - TAccountSystemProgram extends string | IAccountMeta = '11111111111111111111111111111111', + TAccountSystemProgram extends string | IAccountMeta = "11111111111111111111111111111111", TRemainingAccounts extends readonly IAccountMeta[] = [], > = IInstruction & IInstructionWithData & IInstructionWithAccounts< [ - TAccountAuthority extends string ? WritableSignerAccount & IAccountSignerMeta : TAccountAuthority, + TAccountAuthority extends string + ? WritableSignerAccount & IAccountSignerMeta + : TAccountAuthority, TAccountConfig extends string ? WritableAccount : TAccountConfig, TAccountSystemProgram extends string ? ReadonlyAccount : TAccountSystemProgram, ...TRemainingAccounts, @@ -56,14 +58,17 @@ export type InitInstruction< export type InitInstructionData = { discriminator: number }; -export type InitInstructionDataArgs = {}; +export type InitInstructionDataArgs = Record; export function getInitInstructionDataEncoder(): Encoder { - return transformEncoder(getStructEncoder([['discriminator', getU8Encoder()]]), (value) => ({ ...value, discriminator: 241 })); + return transformEncoder(getStructEncoder([["discriminator", getU8Encoder()]]), (value) => ({ + ...value, + discriminator: 241, + })); } export function getInitInstructionDataDecoder(): Decoder { - return getStructDecoder([['discriminator', getU8Decoder()]]); + return getStructDecoder([["discriminator", getU8Decoder()]]); } export function getInitInstructionDataCodec(): Codec { @@ -105,12 +110,16 @@ export async function getInitInstructionAsync< accounts.config.value = await findConfigPda(); } if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { - accounts: [getAccountMeta(accounts.authority), getAccountMeta(accounts.config), getAccountMeta(accounts.systemProgram)], + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.config), + getAccountMeta(accounts.systemProgram), + ], programAddress, data: getInitInstructionDataEncoder().encode({}), } as InitInstruction; @@ -150,12 +159,16 @@ export function getInitInstruction< // Resolve default values. if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { - accounts: [getAccountMeta(accounts.authority), getAccountMeta(accounts.config), getAccountMeta(accounts.systemProgram)], + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.config), + getAccountMeta(accounts.systemProgram), + ], programAddress, data: getInitInstructionDataEncoder().encode({}), } as InitInstruction; @@ -181,11 +194,11 @@ export function parseInitInstruction { if (instruction.accounts.length < 3) { // TODO: Coded error. - throw new Error('Not enough accounts'); + throw new Error("Not enough accounts"); } let accountIndex = 0; const getNextAccount = () => { - const accountMeta = instruction.accounts?.[accountIndex]!; + const accountMeta = instruction.accounts[accountIndex]; accountIndex += 1; return accountMeta; }; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/setupExtraMetas.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/setupExtraMetas.ts index 021e6729c..c9004cd3b 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/setupExtraMetas.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/setupExtraMetas.ts @@ -28,10 +28,10 @@ import { transformEncoder, type WritableAccount, type WritableSignerAccount, -} from '@solana/kit'; -import { findConfigPda, findExtraMetasPda } from '../pdas'; -import { BLOCK_LIST_PROGRAM_ADDRESS } from '../programs'; -import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +} from "@solana/kit"; +import { findConfigPda, findExtraMetasPda } from "../pdas"; +import { BLOCK_LIST_PROGRAM_ADDRESS } from "../programs"; +import { getAccountMetaFactory, type ResolvedAccount } from "../shared"; export const SETUP_EXTRA_METAS_DISCRIMINATOR = 106; @@ -45,13 +45,15 @@ export type SetupExtraMetasInstruction< TAccountConfig extends string | IAccountMeta = string, TAccountMint extends string | IAccountMeta = string, TAccountExtraMetas extends string | IAccountMeta = string, - TAccountSystemProgram extends string | IAccountMeta = '11111111111111111111111111111111', + TAccountSystemProgram extends string | IAccountMeta = "11111111111111111111111111111111", TRemainingAccounts extends readonly IAccountMeta[] = [], > = IInstruction & IInstructionWithData & IInstructionWithAccounts< [ - TAccountAuthority extends string ? WritableSignerAccount & IAccountSignerMeta : TAccountAuthority, + TAccountAuthority extends string + ? WritableSignerAccount & IAccountSignerMeta + : TAccountAuthority, TAccountConfig extends string ? ReadonlyAccount : TAccountConfig, TAccountMint extends string ? ReadonlyAccount : TAccountMint, TAccountExtraMetas extends string ? WritableAccount : TAccountExtraMetas, @@ -70,8 +72,8 @@ export type SetupExtraMetasInstructionDataArgs = { checkBothWallets?: boolean }; export function getSetupExtraMetasInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([ - ['discriminator', getU8Encoder()], - ['checkBothWallets', getBooleanEncoder()], + ["discriminator", getU8Encoder()], + ["checkBothWallets", getBooleanEncoder()], ]), (value) => ({ ...value, @@ -83,12 +85,15 @@ export function getSetupExtraMetasInstructionDataEncoder(): Encoder { return getStructDecoder([ - ['discriminator', getU8Decoder()], - ['checkBothWallets', getBooleanDecoder()], + ["discriminator", getU8Decoder()], + ["checkBothWallets", getBooleanDecoder()], ]); } -export function getSetupExtraMetasInstructionDataCodec(): Codec { +export function getSetupExtraMetasInstructionDataCodec(): Codec< + SetupExtraMetasInstructionDataArgs, + SetupExtraMetasInstructionData +> { return combineCodec(getSetupExtraMetasInstructionDataEncoder(), getSetupExtraMetasInstructionDataDecoder()); } @@ -104,7 +109,7 @@ export type SetupExtraMetasAsyncInput< mint: Address; extraMetas?: Address; systemProgram?: Address; - checkBothWallets?: SetupExtraMetasInstructionDataArgs['checkBothWallets']; + checkBothWallets?: SetupExtraMetasInstructionDataArgs["checkBothWallets"]; }; export async function getSetupExtraMetasInstructionAsync< @@ -115,9 +120,24 @@ export async function getSetupExtraMetasInstructionAsync< TAccountSystemProgram extends string, TProgramAddress extends Address = typeof BLOCK_LIST_PROGRAM_ADDRESS, >( - input: SetupExtraMetasAsyncInput, + input: SetupExtraMetasAsyncInput< + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + >, config?: { programAddress?: TProgramAddress }, -): Promise> { +): Promise< + SetupExtraMetasInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + > +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -142,10 +162,10 @@ export async function getSetupExtraMetasInstructionAsync< accounts.extraMetas.value = await findExtraMetasPda(); } if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -156,7 +176,14 @@ export async function getSetupExtraMetasInstructionAsync< ], programAddress, data: getSetupExtraMetasInstructionDataEncoder().encode(args as SetupExtraMetasInstructionDataArgs), - } as SetupExtraMetasInstruction; + } as SetupExtraMetasInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + >; return instruction; } @@ -173,7 +200,7 @@ export type SetupExtraMetasInput< mint: Address; extraMetas: Address; systemProgram?: Address; - checkBothWallets?: SetupExtraMetasInstructionDataArgs['checkBothWallets']; + checkBothWallets?: SetupExtraMetasInstructionDataArgs["checkBothWallets"]; }; export function getSetupExtraMetasInstruction< @@ -184,9 +211,22 @@ export function getSetupExtraMetasInstruction< TAccountSystemProgram extends string, TProgramAddress extends Address = typeof BLOCK_LIST_PROGRAM_ADDRESS, >( - input: SetupExtraMetasInput, + input: SetupExtraMetasInput< + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + >, config?: { programAddress?: TProgramAddress }, -): SetupExtraMetasInstruction { +): SetupExtraMetasInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -205,10 +245,10 @@ export function getSetupExtraMetasInstruction< // Resolve default values. if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -219,7 +259,14 @@ export function getSetupExtraMetasInstruction< ], programAddress, data: getSetupExtraMetasInstructionDataEncoder().encode(args as SetupExtraMetasInstructionDataArgs), - } as SetupExtraMetasInstruction; + } as SetupExtraMetasInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + >; return instruction; } @@ -244,11 +291,11 @@ export function parseSetupExtraMetasInstruction { if (instruction.accounts.length < 5) { // TODO: Coded error. - throw new Error('Not enough accounts'); + throw new Error("Not enough accounts"); } let accountIndex = 0; const getNextAccount = () => { - const accountMeta = instruction.accounts?.[accountIndex]!; + const accountMeta = instruction.accounts[accountIndex]; accountIndex += 1; return accountMeta; }; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/unblockWallet.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/unblockWallet.ts index d17158efe..40b3f33f0 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/unblockWallet.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/instructions/unblockWallet.ts @@ -26,10 +26,10 @@ import { transformEncoder, type WritableAccount, type WritableSignerAccount, -} from '@solana/kit'; -import { findConfigPda } from '../pdas'; -import { BLOCK_LIST_PROGRAM_ADDRESS } from '../programs'; -import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +} from "@solana/kit"; +import { findConfigPda } from "../pdas"; +import { BLOCK_LIST_PROGRAM_ADDRESS } from "../programs"; +import { getAccountMetaFactory, type ResolvedAccount } from "../shared"; export const UNBLOCK_WALLET_DISCRIMINATOR = 243; @@ -42,13 +42,15 @@ export type UnblockWalletInstruction< TAccountAuthority extends string | IAccountMeta = string, TAccountConfig extends string | IAccountMeta = string, TAccountWalletBlock extends string | IAccountMeta = string, - TAccountSystemProgram extends string | IAccountMeta = '11111111111111111111111111111111', + TAccountSystemProgram extends string | IAccountMeta = "11111111111111111111111111111111", TRemainingAccounts extends readonly IAccountMeta[] = [], > = IInstruction & IInstructionWithData & IInstructionWithAccounts< [ - TAccountAuthority extends string ? WritableSignerAccount & IAccountSignerMeta : TAccountAuthority, + TAccountAuthority extends string + ? WritableSignerAccount & IAccountSignerMeta + : TAccountAuthority, TAccountConfig extends string ? WritableAccount : TAccountConfig, TAccountWalletBlock extends string ? WritableAccount : TAccountWalletBlock, TAccountSystemProgram extends string ? ReadonlyAccount : TAccountSystemProgram, @@ -58,17 +60,23 @@ export type UnblockWalletInstruction< export type UnblockWalletInstructionData = { discriminator: number }; -export type UnblockWalletInstructionDataArgs = {}; +export type UnblockWalletInstructionDataArgs = Record; export function getUnblockWalletInstructionDataEncoder(): Encoder { - return transformEncoder(getStructEncoder([['discriminator', getU8Encoder()]]), (value) => ({ ...value, discriminator: 243 })); + return transformEncoder(getStructEncoder([["discriminator", getU8Encoder()]]), (value) => ({ + ...value, + discriminator: 243, + })); } export function getUnblockWalletInstructionDataDecoder(): Decoder { - return getStructDecoder([['discriminator', getU8Decoder()]]); + return getStructDecoder([["discriminator", getU8Decoder()]]); } -export function getUnblockWalletInstructionDataCodec(): Codec { +export function getUnblockWalletInstructionDataCodec(): Codec< + UnblockWalletInstructionDataArgs, + UnblockWalletInstructionData +> { return combineCodec(getUnblockWalletInstructionDataEncoder(), getUnblockWalletInstructionDataDecoder()); } @@ -93,7 +101,15 @@ export async function getUnblockWalletInstructionAsync< >( input: UnblockWalletAsyncInput, config?: { programAddress?: TProgramAddress }, -): Promise> { +): Promise< + UnblockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWalletBlock, + TAccountSystemProgram + > +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -111,10 +127,10 @@ export async function getUnblockWalletInstructionAsync< accounts.config.value = await findConfigPda(); } if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -124,7 +140,13 @@ export async function getUnblockWalletInstructionAsync< ], programAddress, data: getUnblockWalletInstructionDataEncoder().encode({}), - } as UnblockWalletInstruction; + } as UnblockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWalletBlock, + TAccountSystemProgram + >; return instruction; } @@ -150,7 +172,13 @@ export function getUnblockWalletInstruction< >( input: UnblockWalletInput, config?: { programAddress?: TProgramAddress }, -): UnblockWalletInstruction { +): UnblockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWalletBlock, + TAccountSystemProgram +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -165,10 +193,10 @@ export function getUnblockWalletInstruction< // Resolve default values. if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -178,7 +206,13 @@ export function getUnblockWalletInstruction< ], programAddress, data: getUnblockWalletInstructionDataEncoder().encode({}), - } as UnblockWalletInstruction; + } as UnblockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWalletBlock, + TAccountSystemProgram + >; return instruction; } @@ -202,11 +236,11 @@ export function parseUnblockWalletInstruction { if (instruction.accounts.length < 4) { // TODO: Coded error. - throw new Error('Not enough accounts'); + throw new Error("Not enough accounts"); } let accountIndex = 0; const getNextAccount = () => { - const accountMeta = instruction.accounts?.[accountIndex]!; + const accountMeta = instruction.accounts[accountIndex]; accountIndex += 1; return accountMeta; }; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/config.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/config.ts index 343f6f4ce..be83310f6 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/config.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/config.ts @@ -6,12 +6,16 @@ * @see https://github.com/codama-idl/codama */ -import { type Address, getProgramDerivedAddress, getUtf8Encoder, type ProgramDerivedAddress } from '@solana/kit'; +import { type Address, getProgramDerivedAddress, getUtf8Encoder, type ProgramDerivedAddress } from "@solana/kit"; -export async function findConfigPda(config: { programAddress?: Address | undefined } = {}): Promise { - const { programAddress = 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf' as Address<'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf'> } = config; +export async function findConfigPda( + config: { programAddress?: Address | undefined } = {}, +): Promise { + const { + programAddress = "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf" as Address<"BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf">, + } = config; return await getProgramDerivedAddress({ programAddress, - seeds: [getUtf8Encoder().encode('config')], + seeds: [getUtf8Encoder().encode("config")], }); } diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/extraMetas.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/extraMetas.ts index a66a9d189..db4a84483 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/extraMetas.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/extraMetas.ts @@ -6,7 +6,13 @@ * @see https://github.com/codama-idl/codama */ -import { type Address, getAddressEncoder, getProgramDerivedAddress, getUtf8Encoder, type ProgramDerivedAddress } from '@solana/kit'; +import { + type Address, + getAddressEncoder, + getProgramDerivedAddress, + getUtf8Encoder, + type ProgramDerivedAddress, +} from "@solana/kit"; export type ExtraMetasSeeds = { mint: Address; @@ -16,9 +22,11 @@ export async function findExtraMetasPda( seeds: ExtraMetasSeeds, config: { programAddress?: Address | undefined } = {}, ): Promise { - const { programAddress = 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf' as Address<'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf'> } = config; + const { + programAddress = "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf" as Address<"BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf">, + } = config; return await getProgramDerivedAddress({ programAddress, - seeds: [getUtf8Encoder().encode('extra-account-metas'), getAddressEncoder().encode(seeds.mint)], + seeds: [getUtf8Encoder().encode("extra-account-metas"), getAddressEncoder().encode(seeds.mint)], }); } diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/index.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/index.ts index ed620eb19..6135b7a67 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/index.ts @@ -6,6 +6,6 @@ * @see https://github.com/codama-idl/codama */ -export * from './config'; -export * from './extraMetas'; -export * from './walletBlock'; +export * from "./config"; +export * from "./extraMetas"; +export * from "./walletBlock"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/walletBlock.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/walletBlock.ts index 1a5e84096..2705fbcef 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/walletBlock.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/pdas/walletBlock.ts @@ -6,7 +6,13 @@ * @see https://github.com/codama-idl/codama */ -import { type Address, getAddressEncoder, getProgramDerivedAddress, getUtf8Encoder, type ProgramDerivedAddress } from '@solana/kit'; +import { + type Address, + getAddressEncoder, + getProgramDerivedAddress, + getUtf8Encoder, + type ProgramDerivedAddress, +} from "@solana/kit"; export type WalletBlockSeeds = { wallet: Address; @@ -16,9 +22,11 @@ export async function findWalletBlockPda( seeds: WalletBlockSeeds, config: { programAddress?: Address | undefined } = {}, ): Promise { - const { programAddress = 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf' as Address<'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf'> } = config; + const { + programAddress = "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf" as Address<"BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf">, + } = config; return await getProgramDerivedAddress({ programAddress, - seeds: [getUtf8Encoder().encode('wallet_block'), getAddressEncoder().encode(seeds.wallet)], + seeds: [getUtf8Encoder().encode("wallet_block"), getAddressEncoder().encode(seeds.wallet)], }); } diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/programs/blockList.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/programs/blockList.ts index 4ba42d741..d22c9ccf9 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/programs/blockList.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/programs/blockList.ts @@ -6,15 +6,16 @@ * @see https://github.com/codama-idl/codama */ -import { type Address, containsBytes, getU8Encoder, type ReadonlyUint8Array } from '@solana/kit'; -import { - type ParsedBlockWalletInstruction, - type ParsedInitInstruction, - type ParsedSetupExtraMetasInstruction, - type ParsedUnblockWalletInstruction, -} from '../instructions'; +import { type Address, containsBytes, getU8Encoder, type ReadonlyUint8Array } from "@solana/kit"; +import type { + ParsedBlockWalletInstruction, + ParsedInitInstruction, + ParsedSetupExtraMetasInstruction, + ParsedUnblockWalletInstruction, +} from "../instructions"; -export const BLOCK_LIST_PROGRAM_ADDRESS = 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf' as Address<'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf'>; +export const BLOCK_LIST_PROGRAM_ADDRESS = + "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf" as Address<"BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf">; export enum BlockListAccount { Config, @@ -23,14 +24,14 @@ export enum BlockListAccount { } export function identifyBlockListAccount(account: { data: ReadonlyUint8Array } | ReadonlyUint8Array): BlockListAccount { - const data = 'data' in account ? account.data : account; + const data = "data" in account ? account.data : account; if (containsBytes(data, getU8Encoder().encode(0), 0)) { return BlockListAccount.Config; } if (containsBytes(data, getU8Encoder().encode(1), 0)) { return BlockListAccount.WalletBlock; } - throw new Error('The provided account could not be identified as a blockList account.'); + throw new Error("The provided account could not be identified as a blockList account."); } export enum BlockListInstruction { @@ -40,8 +41,10 @@ export enum BlockListInstruction { SetupExtraMetas, } -export function identifyBlockListInstruction(instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array): BlockListInstruction { - const data = 'data' in instruction ? instruction.data : instruction; +export function identifyBlockListInstruction( + instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array, +): BlockListInstruction { + const data = "data" in instruction ? instruction.data : instruction; if (containsBytes(data, getU8Encoder().encode(241), 0)) { return BlockListInstruction.Init; } @@ -54,10 +57,10 @@ export function identifyBlockListInstruction(instruction: { data: ReadonlyUint8A if (containsBytes(data, getU8Encoder().encode(106), 0)) { return BlockListInstruction.SetupExtraMetas; } - throw new Error('The provided instruction could not be identified as a blockList instruction.'); + throw new Error("The provided instruction could not be identified as a blockList instruction."); } -export type ParsedBlockListInstruction = +export type ParsedBlockListInstruction = | ({ instructionType: BlockListInstruction.Init; } & ParsedInitInstruction) diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/programs/index.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/programs/index.ts index f945615bd..01ddfbdee 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/programs/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/programs/index.ts @@ -6,4 +6,4 @@ * @see https://github.com/codama-idl/codama */ -export * from './blockList'; +export * from "./blockList"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/shared/index.ts b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/shared/index.ts index 27141fc40..6b3bc4a6a 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/shared/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/pino/sdk/ts/src/shared/index.ts @@ -16,7 +16,7 @@ import { type ProgramDerivedAddress, type TransactionSigner, upgradeRoleToSigner, -} from '@solana/kit'; +} from "@solana/kit"; /** * Asserts that the given value is not null or undefined. @@ -24,7 +24,7 @@ import { */ export function expectSome(value: T | null | undefined): T { if (value == null) { - throw new Error('Expected a value but received null or undefined.'); + throw new Error("Expected a value but received null or undefined."); } return value; } @@ -37,9 +37,9 @@ export function expectAddress( value: Address | ProgramDerivedAddress | TransactionSigner | null | undefined, ): Address { if (!value) { - throw new Error('Expected a Address.'); + throw new Error("Expected a Address."); } - if (typeof value === 'object' && 'address' in value) { + if (typeof value === "object" && "address" in value) { return value.address; } if (Array.isArray(value)) { @@ -56,7 +56,7 @@ export function expectProgramDerivedAddress( value: Address | ProgramDerivedAddress | TransactionSigner | null | undefined, ): ProgramDerivedAddress { if (!value || !Array.isArray(value) || !isProgramDerivedAddress(value)) { - throw new Error('Expected a ProgramDerivedAddress.'); + throw new Error("Expected a ProgramDerivedAddress."); } return value; } @@ -69,7 +69,7 @@ export function expectTransactionSigner( value: Address | ProgramDerivedAddress | TransactionSigner | null | undefined, ): TransactionSigner { if (!value || !isTransactionSigner(value)) { - throw new Error('Expected a TransactionSigner.'); + throw new Error("Expected a TransactionSigner."); } return value; } @@ -80,7 +80,11 @@ export function expectTransactionSigner( */ export type ResolvedAccount< T extends string = string, - U extends Address | ProgramDerivedAddress | TransactionSigner | null = Address | ProgramDerivedAddress | TransactionSigner | null, + U extends Address | ProgramDerivedAddress | TransactionSigner | null = + | Address + | ProgramDerivedAddress + | TransactionSigner + | null, > = { isWritable: boolean; value: U; @@ -98,10 +102,10 @@ export type IInstructionWithByteDelta = { * Get account metas and signers from resolved accounts. * @internal */ -export function getAccountMetaFactory(programAddress: Address, optionalAccountStrategy: 'omitted' | 'programId') { +export function getAccountMetaFactory(programAddress: Address, optionalAccountStrategy: "omitted" | "programId") { return (account: ResolvedAccount): IAccountMeta | IAccountSignerMeta | undefined => { if (!account.value) { - if (optionalAccountStrategy === 'omitted') return; + if (optionalAccountStrategy === "omitted") return; return Object.freeze({ address: programAddress, role: AccountRole.READONLY, @@ -120,5 +124,5 @@ export function getAccountMetaFactory(programAddress: Address, optionalAccountSt export function isTransactionSigner( value: Address | ProgramDerivedAddress | TransactionSigner, ): value is TransactionSigner { - return !!value && typeof value === 'object' && 'address' in value && kitIsTransactionSigner(value); + return !!value && typeof value === "object" && "address" in value && kitIsTransactionSigner(value); } diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/config.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/config.ts index d59757590..03a52b664 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/config.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/config.ts @@ -31,8 +31,8 @@ import { getU64Encoder, type MaybeAccount, type MaybeEncodedAccount, -} from '@solana/kit'; -import { findConfigPda } from '../pdas'; +} from "@solana/kit"; +import { findConfigPda } from "../pdas"; export const CONFIG_DISCRIMINATOR = 0; @@ -54,17 +54,17 @@ export type ConfigArgs = { export function getConfigEncoder(): Encoder { return getStructEncoder([ - ['discriminator', getU8Encoder()], - ['authority', getAddressEncoder()], - ['blockedWalletsCount', getU64Encoder()], + ["discriminator", getU8Encoder()], + ["authority", getAddressEncoder()], + ["blockedWalletsCount", getU64Encoder()], ]); } export function getConfigDecoder(): Decoder { return getStructDecoder([ - ['discriminator', getU8Decoder()], - ['authority', getAddressDecoder()], - ['blockedWalletsCount', getU64Decoder()], + ["discriminator", getU8Decoder()], + ["authority", getAddressDecoder()], + ["blockedWalletsCount", getU64Decoder()], ]); } @@ -72,8 +72,12 @@ export function getConfigCodec(): Codec { return combineCodec(getConfigEncoder(), getConfigDecoder()); } -export function decodeConfig(encodedAccount: EncodedAccount): Account; -export function decodeConfig(encodedAccount: MaybeEncodedAccount): MaybeAccount; +export function decodeConfig( + encodedAccount: EncodedAccount, +): Account; +export function decodeConfig( + encodedAccount: MaybeEncodedAccount, +): MaybeAccount; export function decodeConfig( encodedAccount: EncodedAccount | MaybeEncodedAccount, ): Account | MaybeAccount { diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/extraMetas.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/extraMetas.ts index 3292ead79..93859232f 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/extraMetas.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/extraMetas.ts @@ -25,10 +25,10 @@ import { getStructEncoder, type MaybeAccount, type MaybeEncodedAccount, -} from '@solana/kit'; -import { ExtraMetasSeeds, findExtraMetasPda } from '../pdas'; +} from "@solana/kit"; +import { type ExtraMetasSeeds, findExtraMetasPda } from "../pdas"; -export type ExtraMetas = {}; +export type ExtraMetas = Record; export type ExtraMetasArgs = ExtraMetas; @@ -44,8 +44,12 @@ export function getExtraMetasCodec(): Codec { return combineCodec(getExtraMetasEncoder(), getExtraMetasDecoder()); } -export function decodeExtraMetas(encodedAccount: EncodedAccount): Account; -export function decodeExtraMetas(encodedAccount: MaybeEncodedAccount): MaybeAccount; +export function decodeExtraMetas( + encodedAccount: EncodedAccount, +): Account; +export function decodeExtraMetas( + encodedAccount: MaybeEncodedAccount, +): MaybeAccount; export function decodeExtraMetas( encodedAccount: EncodedAccount | MaybeEncodedAccount, ): Account | MaybeAccount { diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/index.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/index.ts index ed620eb19..6135b7a67 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/index.ts @@ -6,6 +6,6 @@ * @see https://github.com/codama-idl/codama */ -export * from './config'; -export * from './extraMetas'; -export * from './walletBlock'; +export * from "./config"; +export * from "./extraMetas"; +export * from "./walletBlock"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/walletBlock.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/walletBlock.ts index 886a73f79..29a8309a9 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/walletBlock.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/accounts/walletBlock.ts @@ -28,8 +28,8 @@ import { getU8Encoder, type MaybeAccount, type MaybeEncodedAccount, -} from '@solana/kit'; -import { findWalletBlockPda, WalletBlockSeeds } from '../pdas'; +} from "@solana/kit"; +import { findWalletBlockPda, type WalletBlockSeeds } from "../pdas"; export const WALLET_BLOCK_DISCRIMINATOR = 1; @@ -42,18 +42,20 @@ export type WalletBlock = { authority: Address }; export type WalletBlockArgs = WalletBlock; export function getWalletBlockEncoder(): Encoder { - return getStructEncoder([['authority', getAddressEncoder()]]); + return getStructEncoder([["authority", getAddressEncoder()]]); } export function getWalletBlockDecoder(): Decoder { - return getStructDecoder([['authority', getAddressDecoder()]]); + return getStructDecoder([["authority", getAddressDecoder()]]); } export function getWalletBlockCodec(): Codec { return combineCodec(getWalletBlockEncoder(), getWalletBlockDecoder()); } -export function decodeWalletBlock(encodedAccount: EncodedAccount): Account; +export function decodeWalletBlock( + encodedAccount: EncodedAccount, +): Account; export function decodeWalletBlock( encodedAccount: MaybeEncodedAccount, ): MaybeAccount; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/index.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/index.ts index 1002b8203..cf9bea234 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/index.ts @@ -6,7 +6,7 @@ * @see https://github.com/codama-idl/codama */ -export * from './accounts'; -export * from './instructions'; -export * from './pdas'; -export * from './programs'; +export * from "./accounts"; +export * from "./instructions"; +export * from "./pdas"; +export * from "./programs"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/blockWallet.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/blockWallet.ts index b0f1d4d19..e49ba63b7 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/blockWallet.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/blockWallet.ts @@ -26,10 +26,10 @@ import { transformEncoder, type WritableAccount, type WritableSignerAccount, -} from '@solana/kit'; -import { findConfigPda } from '../pdas'; -import { BLOCK_LIST_PROGRAM_ADDRESS } from '../programs'; -import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +} from "@solana/kit"; +import { findConfigPda } from "../pdas"; +import { BLOCK_LIST_PROGRAM_ADDRESS } from "../programs"; +import { getAccountMetaFactory, type ResolvedAccount } from "../shared"; export const BLOCK_WALLET_DISCRIMINATOR = 242; @@ -43,13 +43,15 @@ export type BlockWalletInstruction< TAccountConfig extends string | IAccountMeta = string, TAccountWallet extends string | IAccountMeta = string, TAccountWalletBlock extends string | IAccountMeta = string, - TAccountSystemProgram extends string | IAccountMeta = '11111111111111111111111111111111', + TAccountSystemProgram extends string | IAccountMeta = "11111111111111111111111111111111", TRemainingAccounts extends readonly IAccountMeta[] = [], > = IInstruction & IInstructionWithData & IInstructionWithAccounts< [ - TAccountAuthority extends string ? WritableSignerAccount & IAccountSignerMeta : TAccountAuthority, + TAccountAuthority extends string + ? WritableSignerAccount & IAccountSignerMeta + : TAccountAuthority, TAccountConfig extends string ? WritableAccount : TAccountConfig, TAccountWallet extends string ? ReadonlyAccount : TAccountWallet, TAccountWalletBlock extends string ? WritableAccount : TAccountWalletBlock, @@ -60,17 +62,23 @@ export type BlockWalletInstruction< export type BlockWalletInstructionData = { discriminator: number }; -export type BlockWalletInstructionDataArgs = {}; +export type BlockWalletInstructionDataArgs = Record; export function getBlockWalletInstructionDataEncoder(): Encoder { - return transformEncoder(getStructEncoder([['discriminator', getU8Encoder()]]), (value) => ({ ...value, discriminator: 242 })); + return transformEncoder(getStructEncoder([["discriminator", getU8Encoder()]]), (value) => ({ + ...value, + discriminator: 242, + })); } export function getBlockWalletInstructionDataDecoder(): Decoder { - return getStructDecoder([['discriminator', getU8Decoder()]]); + return getStructDecoder([["discriminator", getU8Decoder()]]); } -export function getBlockWalletInstructionDataCodec(): Codec { +export function getBlockWalletInstructionDataCodec(): Codec< + BlockWalletInstructionDataArgs, + BlockWalletInstructionData +> { return combineCodec(getBlockWalletInstructionDataEncoder(), getBlockWalletInstructionDataDecoder()); } @@ -96,9 +104,24 @@ export async function getBlockWalletInstructionAsync< TAccountSystemProgram extends string, TProgramAddress extends Address = typeof BLOCK_LIST_PROGRAM_ADDRESS, >( - input: BlockWalletAsyncInput, + input: BlockWalletAsyncInput< + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + >, config?: { programAddress?: TProgramAddress }, -): Promise> { +): Promise< + BlockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + > +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -117,10 +140,10 @@ export async function getBlockWalletInstructionAsync< accounts.config.value = await findConfigPda(); } if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -131,7 +154,14 @@ export async function getBlockWalletInstructionAsync< ], programAddress, data: getBlockWalletInstructionDataEncoder().encode({}), - } as BlockWalletInstruction; + } as BlockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + >; return instruction; } @@ -158,9 +188,22 @@ export function getBlockWalletInstruction< TAccountSystemProgram extends string, TProgramAddress extends Address = typeof BLOCK_LIST_PROGRAM_ADDRESS, >( - input: BlockWalletInput, + input: BlockWalletInput< + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + >, config?: { programAddress?: TProgramAddress }, -): BlockWalletInstruction { +): BlockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -176,10 +219,10 @@ export function getBlockWalletInstruction< // Resolve default values. if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -190,7 +233,14 @@ export function getBlockWalletInstruction< ], programAddress, data: getBlockWalletInstructionDataEncoder().encode({}), - } as BlockWalletInstruction; + } as BlockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWallet, + TAccountWalletBlock, + TAccountSystemProgram + >; return instruction; } @@ -215,11 +265,11 @@ export function parseBlockWalletInstruction { if (instruction.accounts.length < 5) { // TODO: Coded error. - throw new Error('Not enough accounts'); + throw new Error("Not enough accounts"); } let accountIndex = 0; const getNextAccount = () => { - const accountMeta = instruction.accounts?.[accountIndex]!; + const accountMeta = instruction.accounts[accountIndex]; accountIndex += 1; return accountMeta; }; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/index.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/index.ts index 864cb10b3..f4bba88c5 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/index.ts @@ -6,7 +6,7 @@ * @see https://github.com/codama-idl/codama */ -export * from './blockWallet'; -export * from './init'; -export * from './setupExtraMetas'; -export * from './unblockWallet'; +export * from "./blockWallet"; +export * from "./init"; +export * from "./setupExtraMetas"; +export * from "./unblockWallet"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/init.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/init.ts index f02a8fe63..860840983 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/init.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/init.ts @@ -26,10 +26,10 @@ import { transformEncoder, type WritableAccount, type WritableSignerAccount, -} from '@solana/kit'; -import { findConfigPda } from '../pdas'; -import { BLOCK_LIST_PROGRAM_ADDRESS } from '../programs'; -import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +} from "@solana/kit"; +import { findConfigPda } from "../pdas"; +import { BLOCK_LIST_PROGRAM_ADDRESS } from "../programs"; +import { getAccountMetaFactory, type ResolvedAccount } from "../shared"; export const INIT_DISCRIMINATOR = 241; @@ -41,13 +41,15 @@ export type InitInstruction< TProgram extends string = typeof BLOCK_LIST_PROGRAM_ADDRESS, TAccountAuthority extends string | IAccountMeta = string, TAccountConfig extends string | IAccountMeta = string, - TAccountSystemProgram extends string | IAccountMeta = '11111111111111111111111111111111', + TAccountSystemProgram extends string | IAccountMeta = "11111111111111111111111111111111", TRemainingAccounts extends readonly IAccountMeta[] = [], > = IInstruction & IInstructionWithData & IInstructionWithAccounts< [ - TAccountAuthority extends string ? WritableSignerAccount & IAccountSignerMeta : TAccountAuthority, + TAccountAuthority extends string + ? WritableSignerAccount & IAccountSignerMeta + : TAccountAuthority, TAccountConfig extends string ? WritableAccount : TAccountConfig, TAccountSystemProgram extends string ? ReadonlyAccount : TAccountSystemProgram, ...TRemainingAccounts, @@ -56,14 +58,17 @@ export type InitInstruction< export type InitInstructionData = { discriminator: number }; -export type InitInstructionDataArgs = {}; +export type InitInstructionDataArgs = Record; export function getInitInstructionDataEncoder(): Encoder { - return transformEncoder(getStructEncoder([['discriminator', getU8Encoder()]]), (value) => ({ ...value, discriminator: 241 })); + return transformEncoder(getStructEncoder([["discriminator", getU8Encoder()]]), (value) => ({ + ...value, + discriminator: 241, + })); } export function getInitInstructionDataDecoder(): Decoder { - return getStructDecoder([['discriminator', getU8Decoder()]]); + return getStructDecoder([["discriminator", getU8Decoder()]]); } export function getInitInstructionDataCodec(): Codec { @@ -105,12 +110,16 @@ export async function getInitInstructionAsync< accounts.config.value = await findConfigPda(); } if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { - accounts: [getAccountMeta(accounts.authority), getAccountMeta(accounts.config), getAccountMeta(accounts.systemProgram)], + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.config), + getAccountMeta(accounts.systemProgram), + ], programAddress, data: getInitInstructionDataEncoder().encode({}), } as InitInstruction; @@ -150,12 +159,16 @@ export function getInitInstruction< // Resolve default values. if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { - accounts: [getAccountMeta(accounts.authority), getAccountMeta(accounts.config), getAccountMeta(accounts.systemProgram)], + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.config), + getAccountMeta(accounts.systemProgram), + ], programAddress, data: getInitInstructionDataEncoder().encode({}), } as InitInstruction; @@ -181,11 +194,11 @@ export function parseInitInstruction { if (instruction.accounts.length < 3) { // TODO: Coded error. - throw new Error('Not enough accounts'); + throw new Error("Not enough accounts"); } let accountIndex = 0; const getNextAccount = () => { - const accountMeta = instruction.accounts?.[accountIndex]!; + const accountMeta = instruction.accounts[accountIndex]; accountIndex += 1; return accountMeta; }; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/setupExtraMetas.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/setupExtraMetas.ts index 021e6729c..c9004cd3b 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/setupExtraMetas.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/setupExtraMetas.ts @@ -28,10 +28,10 @@ import { transformEncoder, type WritableAccount, type WritableSignerAccount, -} from '@solana/kit'; -import { findConfigPda, findExtraMetasPda } from '../pdas'; -import { BLOCK_LIST_PROGRAM_ADDRESS } from '../programs'; -import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +} from "@solana/kit"; +import { findConfigPda, findExtraMetasPda } from "../pdas"; +import { BLOCK_LIST_PROGRAM_ADDRESS } from "../programs"; +import { getAccountMetaFactory, type ResolvedAccount } from "../shared"; export const SETUP_EXTRA_METAS_DISCRIMINATOR = 106; @@ -45,13 +45,15 @@ export type SetupExtraMetasInstruction< TAccountConfig extends string | IAccountMeta = string, TAccountMint extends string | IAccountMeta = string, TAccountExtraMetas extends string | IAccountMeta = string, - TAccountSystemProgram extends string | IAccountMeta = '11111111111111111111111111111111', + TAccountSystemProgram extends string | IAccountMeta = "11111111111111111111111111111111", TRemainingAccounts extends readonly IAccountMeta[] = [], > = IInstruction & IInstructionWithData & IInstructionWithAccounts< [ - TAccountAuthority extends string ? WritableSignerAccount & IAccountSignerMeta : TAccountAuthority, + TAccountAuthority extends string + ? WritableSignerAccount & IAccountSignerMeta + : TAccountAuthority, TAccountConfig extends string ? ReadonlyAccount : TAccountConfig, TAccountMint extends string ? ReadonlyAccount : TAccountMint, TAccountExtraMetas extends string ? WritableAccount : TAccountExtraMetas, @@ -70,8 +72,8 @@ export type SetupExtraMetasInstructionDataArgs = { checkBothWallets?: boolean }; export function getSetupExtraMetasInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([ - ['discriminator', getU8Encoder()], - ['checkBothWallets', getBooleanEncoder()], + ["discriminator", getU8Encoder()], + ["checkBothWallets", getBooleanEncoder()], ]), (value) => ({ ...value, @@ -83,12 +85,15 @@ export function getSetupExtraMetasInstructionDataEncoder(): Encoder { return getStructDecoder([ - ['discriminator', getU8Decoder()], - ['checkBothWallets', getBooleanDecoder()], + ["discriminator", getU8Decoder()], + ["checkBothWallets", getBooleanDecoder()], ]); } -export function getSetupExtraMetasInstructionDataCodec(): Codec { +export function getSetupExtraMetasInstructionDataCodec(): Codec< + SetupExtraMetasInstructionDataArgs, + SetupExtraMetasInstructionData +> { return combineCodec(getSetupExtraMetasInstructionDataEncoder(), getSetupExtraMetasInstructionDataDecoder()); } @@ -104,7 +109,7 @@ export type SetupExtraMetasAsyncInput< mint: Address; extraMetas?: Address; systemProgram?: Address; - checkBothWallets?: SetupExtraMetasInstructionDataArgs['checkBothWallets']; + checkBothWallets?: SetupExtraMetasInstructionDataArgs["checkBothWallets"]; }; export async function getSetupExtraMetasInstructionAsync< @@ -115,9 +120,24 @@ export async function getSetupExtraMetasInstructionAsync< TAccountSystemProgram extends string, TProgramAddress extends Address = typeof BLOCK_LIST_PROGRAM_ADDRESS, >( - input: SetupExtraMetasAsyncInput, + input: SetupExtraMetasAsyncInput< + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + >, config?: { programAddress?: TProgramAddress }, -): Promise> { +): Promise< + SetupExtraMetasInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + > +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -142,10 +162,10 @@ export async function getSetupExtraMetasInstructionAsync< accounts.extraMetas.value = await findExtraMetasPda(); } if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -156,7 +176,14 @@ export async function getSetupExtraMetasInstructionAsync< ], programAddress, data: getSetupExtraMetasInstructionDataEncoder().encode(args as SetupExtraMetasInstructionDataArgs), - } as SetupExtraMetasInstruction; + } as SetupExtraMetasInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + >; return instruction; } @@ -173,7 +200,7 @@ export type SetupExtraMetasInput< mint: Address; extraMetas: Address; systemProgram?: Address; - checkBothWallets?: SetupExtraMetasInstructionDataArgs['checkBothWallets']; + checkBothWallets?: SetupExtraMetasInstructionDataArgs["checkBothWallets"]; }; export function getSetupExtraMetasInstruction< @@ -184,9 +211,22 @@ export function getSetupExtraMetasInstruction< TAccountSystemProgram extends string, TProgramAddress extends Address = typeof BLOCK_LIST_PROGRAM_ADDRESS, >( - input: SetupExtraMetasInput, + input: SetupExtraMetasInput< + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + >, config?: { programAddress?: TProgramAddress }, -): SetupExtraMetasInstruction { +): SetupExtraMetasInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -205,10 +245,10 @@ export function getSetupExtraMetasInstruction< // Resolve default values. if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -219,7 +259,14 @@ export function getSetupExtraMetasInstruction< ], programAddress, data: getSetupExtraMetasInstructionDataEncoder().encode(args as SetupExtraMetasInstructionDataArgs), - } as SetupExtraMetasInstruction; + } as SetupExtraMetasInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountMint, + TAccountExtraMetas, + TAccountSystemProgram + >; return instruction; } @@ -244,11 +291,11 @@ export function parseSetupExtraMetasInstruction { if (instruction.accounts.length < 5) { // TODO: Coded error. - throw new Error('Not enough accounts'); + throw new Error("Not enough accounts"); } let accountIndex = 0; const getNextAccount = () => { - const accountMeta = instruction.accounts?.[accountIndex]!; + const accountMeta = instruction.accounts[accountIndex]; accountIndex += 1; return accountMeta; }; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/unblockWallet.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/unblockWallet.ts index d17158efe..40b3f33f0 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/unblockWallet.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/instructions/unblockWallet.ts @@ -26,10 +26,10 @@ import { transformEncoder, type WritableAccount, type WritableSignerAccount, -} from '@solana/kit'; -import { findConfigPda } from '../pdas'; -import { BLOCK_LIST_PROGRAM_ADDRESS } from '../programs'; -import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +} from "@solana/kit"; +import { findConfigPda } from "../pdas"; +import { BLOCK_LIST_PROGRAM_ADDRESS } from "../programs"; +import { getAccountMetaFactory, type ResolvedAccount } from "../shared"; export const UNBLOCK_WALLET_DISCRIMINATOR = 243; @@ -42,13 +42,15 @@ export type UnblockWalletInstruction< TAccountAuthority extends string | IAccountMeta = string, TAccountConfig extends string | IAccountMeta = string, TAccountWalletBlock extends string | IAccountMeta = string, - TAccountSystemProgram extends string | IAccountMeta = '11111111111111111111111111111111', + TAccountSystemProgram extends string | IAccountMeta = "11111111111111111111111111111111", TRemainingAccounts extends readonly IAccountMeta[] = [], > = IInstruction & IInstructionWithData & IInstructionWithAccounts< [ - TAccountAuthority extends string ? WritableSignerAccount & IAccountSignerMeta : TAccountAuthority, + TAccountAuthority extends string + ? WritableSignerAccount & IAccountSignerMeta + : TAccountAuthority, TAccountConfig extends string ? WritableAccount : TAccountConfig, TAccountWalletBlock extends string ? WritableAccount : TAccountWalletBlock, TAccountSystemProgram extends string ? ReadonlyAccount : TAccountSystemProgram, @@ -58,17 +60,23 @@ export type UnblockWalletInstruction< export type UnblockWalletInstructionData = { discriminator: number }; -export type UnblockWalletInstructionDataArgs = {}; +export type UnblockWalletInstructionDataArgs = Record; export function getUnblockWalletInstructionDataEncoder(): Encoder { - return transformEncoder(getStructEncoder([['discriminator', getU8Encoder()]]), (value) => ({ ...value, discriminator: 243 })); + return transformEncoder(getStructEncoder([["discriminator", getU8Encoder()]]), (value) => ({ + ...value, + discriminator: 243, + })); } export function getUnblockWalletInstructionDataDecoder(): Decoder { - return getStructDecoder([['discriminator', getU8Decoder()]]); + return getStructDecoder([["discriminator", getU8Decoder()]]); } -export function getUnblockWalletInstructionDataCodec(): Codec { +export function getUnblockWalletInstructionDataCodec(): Codec< + UnblockWalletInstructionDataArgs, + UnblockWalletInstructionData +> { return combineCodec(getUnblockWalletInstructionDataEncoder(), getUnblockWalletInstructionDataDecoder()); } @@ -93,7 +101,15 @@ export async function getUnblockWalletInstructionAsync< >( input: UnblockWalletAsyncInput, config?: { programAddress?: TProgramAddress }, -): Promise> { +): Promise< + UnblockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWalletBlock, + TAccountSystemProgram + > +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -111,10 +127,10 @@ export async function getUnblockWalletInstructionAsync< accounts.config.value = await findConfigPda(); } if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -124,7 +140,13 @@ export async function getUnblockWalletInstructionAsync< ], programAddress, data: getUnblockWalletInstructionDataEncoder().encode({}), - } as UnblockWalletInstruction; + } as UnblockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWalletBlock, + TAccountSystemProgram + >; return instruction; } @@ -150,7 +172,13 @@ export function getUnblockWalletInstruction< >( input: UnblockWalletInput, config?: { programAddress?: TProgramAddress }, -): UnblockWalletInstruction { +): UnblockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWalletBlock, + TAccountSystemProgram +> { // Program address. const programAddress = config?.programAddress ?? BLOCK_LIST_PROGRAM_ADDRESS; @@ -165,10 +193,10 @@ export function getUnblockWalletInstruction< // Resolve default values. if (!accounts.systemProgram.value) { - accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + accounts.systemProgram.value = "11111111111111111111111111111111" as Address<"11111111111111111111111111111111">; } - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); const instruction = { accounts: [ getAccountMeta(accounts.authority), @@ -178,7 +206,13 @@ export function getUnblockWalletInstruction< ], programAddress, data: getUnblockWalletInstructionDataEncoder().encode({}), - } as UnblockWalletInstruction; + } as UnblockWalletInstruction< + TProgramAddress, + TAccountAuthority, + TAccountConfig, + TAccountWalletBlock, + TAccountSystemProgram + >; return instruction; } @@ -202,11 +236,11 @@ export function parseUnblockWalletInstruction { if (instruction.accounts.length < 4) { // TODO: Coded error. - throw new Error('Not enough accounts'); + throw new Error("Not enough accounts"); } let accountIndex = 0; const getNextAccount = () => { - const accountMeta = instruction.accounts?.[accountIndex]!; + const accountMeta = instruction.accounts[accountIndex]; accountIndex += 1; return accountMeta; }; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/config.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/config.ts index 343f6f4ce..be83310f6 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/config.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/config.ts @@ -6,12 +6,16 @@ * @see https://github.com/codama-idl/codama */ -import { type Address, getProgramDerivedAddress, getUtf8Encoder, type ProgramDerivedAddress } from '@solana/kit'; +import { type Address, getProgramDerivedAddress, getUtf8Encoder, type ProgramDerivedAddress } from "@solana/kit"; -export async function findConfigPda(config: { programAddress?: Address | undefined } = {}): Promise { - const { programAddress = 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf' as Address<'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf'> } = config; +export async function findConfigPda( + config: { programAddress?: Address | undefined } = {}, +): Promise { + const { + programAddress = "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf" as Address<"BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf">, + } = config; return await getProgramDerivedAddress({ programAddress, - seeds: [getUtf8Encoder().encode('config')], + seeds: [getUtf8Encoder().encode("config")], }); } diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/extraMetas.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/extraMetas.ts index a66a9d189..db4a84483 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/extraMetas.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/extraMetas.ts @@ -6,7 +6,13 @@ * @see https://github.com/codama-idl/codama */ -import { type Address, getAddressEncoder, getProgramDerivedAddress, getUtf8Encoder, type ProgramDerivedAddress } from '@solana/kit'; +import { + type Address, + getAddressEncoder, + getProgramDerivedAddress, + getUtf8Encoder, + type ProgramDerivedAddress, +} from "@solana/kit"; export type ExtraMetasSeeds = { mint: Address; @@ -16,9 +22,11 @@ export async function findExtraMetasPda( seeds: ExtraMetasSeeds, config: { programAddress?: Address | undefined } = {}, ): Promise { - const { programAddress = 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf' as Address<'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf'> } = config; + const { + programAddress = "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf" as Address<"BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf">, + } = config; return await getProgramDerivedAddress({ programAddress, - seeds: [getUtf8Encoder().encode('extra-account-metas'), getAddressEncoder().encode(seeds.mint)], + seeds: [getUtf8Encoder().encode("extra-account-metas"), getAddressEncoder().encode(seeds.mint)], }); } diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/index.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/index.ts index ed620eb19..6135b7a67 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/index.ts @@ -6,6 +6,6 @@ * @see https://github.com/codama-idl/codama */ -export * from './config'; -export * from './extraMetas'; -export * from './walletBlock'; +export * from "./config"; +export * from "./extraMetas"; +export * from "./walletBlock"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/walletBlock.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/walletBlock.ts index 1a5e84096..2705fbcef 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/walletBlock.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/pdas/walletBlock.ts @@ -6,7 +6,13 @@ * @see https://github.com/codama-idl/codama */ -import { type Address, getAddressEncoder, getProgramDerivedAddress, getUtf8Encoder, type ProgramDerivedAddress } from '@solana/kit'; +import { + type Address, + getAddressEncoder, + getProgramDerivedAddress, + getUtf8Encoder, + type ProgramDerivedAddress, +} from "@solana/kit"; export type WalletBlockSeeds = { wallet: Address; @@ -16,9 +22,11 @@ export async function findWalletBlockPda( seeds: WalletBlockSeeds, config: { programAddress?: Address | undefined } = {}, ): Promise { - const { programAddress = 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf' as Address<'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf'> } = config; + const { + programAddress = "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf" as Address<"BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf">, + } = config; return await getProgramDerivedAddress({ programAddress, - seeds: [getUtf8Encoder().encode('wallet_block'), getAddressEncoder().encode(seeds.wallet)], + seeds: [getUtf8Encoder().encode("wallet_block"), getAddressEncoder().encode(seeds.wallet)], }); } diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/programs/blockList.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/programs/blockList.ts index 4ba42d741..d22c9ccf9 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/programs/blockList.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/programs/blockList.ts @@ -6,15 +6,16 @@ * @see https://github.com/codama-idl/codama */ -import { type Address, containsBytes, getU8Encoder, type ReadonlyUint8Array } from '@solana/kit'; -import { - type ParsedBlockWalletInstruction, - type ParsedInitInstruction, - type ParsedSetupExtraMetasInstruction, - type ParsedUnblockWalletInstruction, -} from '../instructions'; +import { type Address, containsBytes, getU8Encoder, type ReadonlyUint8Array } from "@solana/kit"; +import type { + ParsedBlockWalletInstruction, + ParsedInitInstruction, + ParsedSetupExtraMetasInstruction, + ParsedUnblockWalletInstruction, +} from "../instructions"; -export const BLOCK_LIST_PROGRAM_ADDRESS = 'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf' as Address<'BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf'>; +export const BLOCK_LIST_PROGRAM_ADDRESS = + "BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf" as Address<"BLoCKLSG2qMQ9YxEyrrKKAQzthvW4Lu8Eyv74axF6mf">; export enum BlockListAccount { Config, @@ -23,14 +24,14 @@ export enum BlockListAccount { } export function identifyBlockListAccount(account: { data: ReadonlyUint8Array } | ReadonlyUint8Array): BlockListAccount { - const data = 'data' in account ? account.data : account; + const data = "data" in account ? account.data : account; if (containsBytes(data, getU8Encoder().encode(0), 0)) { return BlockListAccount.Config; } if (containsBytes(data, getU8Encoder().encode(1), 0)) { return BlockListAccount.WalletBlock; } - throw new Error('The provided account could not be identified as a blockList account.'); + throw new Error("The provided account could not be identified as a blockList account."); } export enum BlockListInstruction { @@ -40,8 +41,10 @@ export enum BlockListInstruction { SetupExtraMetas, } -export function identifyBlockListInstruction(instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array): BlockListInstruction { - const data = 'data' in instruction ? instruction.data : instruction; +export function identifyBlockListInstruction( + instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array, +): BlockListInstruction { + const data = "data" in instruction ? instruction.data : instruction; if (containsBytes(data, getU8Encoder().encode(241), 0)) { return BlockListInstruction.Init; } @@ -54,10 +57,10 @@ export function identifyBlockListInstruction(instruction: { data: ReadonlyUint8A if (containsBytes(data, getU8Encoder().encode(106), 0)) { return BlockListInstruction.SetupExtraMetas; } - throw new Error('The provided instruction could not be identified as a blockList instruction.'); + throw new Error("The provided instruction could not be identified as a blockList instruction."); } -export type ParsedBlockListInstruction = +export type ParsedBlockListInstruction = | ({ instructionType: BlockListInstruction.Init; } & ParsedInitInstruction) diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/programs/index.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/programs/index.ts index f945615bd..01ddfbdee 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/programs/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/programs/index.ts @@ -6,4 +6,4 @@ * @see https://github.com/codama-idl/codama */ -export * from './blockList'; +export * from "./blockList"; diff --git a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/shared/index.ts b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/shared/index.ts index 27141fc40..6b3bc4a6a 100644 --- a/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/shared/index.ts +++ b/tokens/token-2022/transfer-hook/pblock-list/sdk/ts/src/shared/index.ts @@ -16,7 +16,7 @@ import { type ProgramDerivedAddress, type TransactionSigner, upgradeRoleToSigner, -} from '@solana/kit'; +} from "@solana/kit"; /** * Asserts that the given value is not null or undefined. @@ -24,7 +24,7 @@ import { */ export function expectSome(value: T | null | undefined): T { if (value == null) { - throw new Error('Expected a value but received null or undefined.'); + throw new Error("Expected a value but received null or undefined."); } return value; } @@ -37,9 +37,9 @@ export function expectAddress( value: Address | ProgramDerivedAddress | TransactionSigner | null | undefined, ): Address { if (!value) { - throw new Error('Expected a Address.'); + throw new Error("Expected a Address."); } - if (typeof value === 'object' && 'address' in value) { + if (typeof value === "object" && "address" in value) { return value.address; } if (Array.isArray(value)) { @@ -56,7 +56,7 @@ export function expectProgramDerivedAddress( value: Address | ProgramDerivedAddress | TransactionSigner | null | undefined, ): ProgramDerivedAddress { if (!value || !Array.isArray(value) || !isProgramDerivedAddress(value)) { - throw new Error('Expected a ProgramDerivedAddress.'); + throw new Error("Expected a ProgramDerivedAddress."); } return value; } @@ -69,7 +69,7 @@ export function expectTransactionSigner( value: Address | ProgramDerivedAddress | TransactionSigner | null | undefined, ): TransactionSigner { if (!value || !isTransactionSigner(value)) { - throw new Error('Expected a TransactionSigner.'); + throw new Error("Expected a TransactionSigner."); } return value; } @@ -80,7 +80,11 @@ export function expectTransactionSigner( */ export type ResolvedAccount< T extends string = string, - U extends Address | ProgramDerivedAddress | TransactionSigner | null = Address | ProgramDerivedAddress | TransactionSigner | null, + U extends Address | ProgramDerivedAddress | TransactionSigner | null = + | Address + | ProgramDerivedAddress + | TransactionSigner + | null, > = { isWritable: boolean; value: U; @@ -98,10 +102,10 @@ export type IInstructionWithByteDelta = { * Get account metas and signers from resolved accounts. * @internal */ -export function getAccountMetaFactory(programAddress: Address, optionalAccountStrategy: 'omitted' | 'programId') { +export function getAccountMetaFactory(programAddress: Address, optionalAccountStrategy: "omitted" | "programId") { return (account: ResolvedAccount): IAccountMeta | IAccountSignerMeta | undefined => { if (!account.value) { - if (optionalAccountStrategy === 'omitted') return; + if (optionalAccountStrategy === "omitted") return; return Object.freeze({ address: programAddress, role: AccountRole.READONLY, @@ -120,5 +124,5 @@ export function getAccountMetaFactory(programAddress: Address, optionalAccountSt export function isTransactionSigner( value: Address | ProgramDerivedAddress | TransactionSigner, ): value is TransactionSigner { - return !!value && typeof value === 'object' && 'address' in value && kitIsTransactionSigner(value); + return !!value && typeof value === "object" && "address" in value && kitIsTransactionSigner(value); } diff --git a/tokens/token-2022/transfer-hook/transfer-cost/anchor/Anchor.toml b/tokens/token-2022/transfer-hook/transfer-cost/anchor/Anchor.toml index 51735fcb2..be58884b7 100644 --- a/tokens/token-2022/transfer-hook/transfer-cost/anchor/Anchor.toml +++ b/tokens/token-2022/transfer-hook/transfer-cost/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -transfer_hook = "FjcHckEgXcBhFmSGai3FRpDLiT6hbpV893n8iTxVd81g" - -# [registry] section removed — no longer used in Anchor 1.0 +transfer_hook = "HbNu4FeF8CpCHr7pMCH7fVcny1KwXSYkSmGTbw9otUdj" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/transfer-hook/transfer-cost/anchor/migrations/deploy.ts b/tokens/token-2022/transfer-hook/transfer-cost/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/transfer-hook/transfer-cost/anchor/migrations/deploy.ts +++ b/tokens/token-2022/transfer-hook/transfer-cost/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/transfer-hook/transfer-cost/anchor/package.json b/tokens/token-2022/transfer-hook/transfer-cost/anchor/package.json index 4faaff4b4..a9773a56c 100644 --- a/tokens/token-2022/transfer-hook/transfer-cost/anchor/package.json +++ b/tokens/token-2022/transfer-hook/transfer-cost/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/transfer-hook/transfer-cost/anchor/pnpm-lock.yaml b/tokens/token-2022/transfer-hook/transfer-cost/anchor/pnpm-lock.yaml index ca2563c13..d2ac84e4a 100644 --- a/tokens/token-2022/transfer-hook/transfer-cost/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/transfer-hook/transfer-cost/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.0 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -860,16 +860,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -887,7 +887,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/Cargo.toml b/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/Cargo.toml index 3c00d558b..457b2d333 100644 --- a/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/Cargo.toml +++ b/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/Cargo.toml @@ -20,13 +20,19 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = "1.0.0-rc.5" -anchor-spl = "1.0.0-rc.5" +anchor-lang = "1.0.0" +anchor-spl = "1.0.0" # SPL crates v3.x-compatible — uses solana-program-error 3.x matching anchor-lang 1.0 spl-discriminator = "0.5.2" spl-tlv-account-resolution = "0.11.1" spl-transfer-hook-interface = "2.1.0" +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/src/lib.rs b/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/src/lib.rs index ad80a1192..5aebeb41d 100644 --- a/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/src/lib.rs +++ b/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/src/lib.rs @@ -23,7 +23,7 @@ use std::{cell::RefMut, str::FromStr}; // transfer-hook program that charges a SOL fee on token transfer // use a delegate and wrapped SOL because signers from initial transfer are not accessible -declare_id!("FjcHckEgXcBhFmSGai3FRpDLiT6hbpV893n8iTxVd81g"); +declare_id!("HbNu4FeF8CpCHr7pMCH7fVcny1KwXSYkSmGTbw9otUdj"); #[error_code] pub enum TransferError { diff --git a/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/tests/test_transfer_hook.rs b/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/tests/test_transfer_hook.rs new file mode 100644 index 000000000..b8993a823 --- /dev/null +++ b/tokens/token-2022/transfer-hook/transfer-cost/anchor/programs/transfer-hook/tests/test_transfer_hook.rs @@ -0,0 +1,84 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::Instruction, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_mint, MintExtension, TOKEN_EXTENSIONS_PROGRAM_ID, + }, + transfer_hook::get_hook_accounts_address, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = transfer_hook::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/transfer_hook.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_initialize_extra_account_meta_list() { + let (mut svm, program_id, payer) = setup(); + let decimals: u8 = 9; + + // Step 1: Create mint with TransferHook extension + let mint = create_token_extensions_mint( + &mut svm, + &payer, + decimals, + None, + &[MintExtension::TransferHook { + program_id: program_id, + }], + ) + .unwrap(); + svm.expire_blockhash(); + + // PDAs + let extra_account_meta_list = + get_hook_accounts_address(&mint, &program_id); + let (counter_pda, _) = Pubkey::find_program_address(&[b"counter"], &program_id); + + // Step 2: Initialize ExtraAccountMetaList (also creates counter PDA) + let init_extra_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::InitializeExtraAccountMetaList {}.data(), + transfer_hook::accounts::InitializeExtraAccountMetaList { + payer: payer.pubkey(), + extra_account_meta_list, + mint, + counter_account: counter_pda, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_extra_ix], &[&payer], &payer.pubkey()).unwrap(); + + // Verify the ExtraAccountMetaList account was created + let account = svm.get_account(&extra_account_meta_list); + assert!( + account.is_some(), + "ExtraAccountMetaList account should exist after initialization" + ); + + // Verify the counter account was created + let counter = svm.get_account(&counter_pda); + assert!( + counter.is_some(), + "Counter account should exist after initialization" + ); +} diff --git a/tokens/token-2022/transfer-hook/transfer-cost/anchor/tests/transfer-hook.ts b/tokens/token-2022/transfer-hook/transfer-cost/anchor/tests/transfer-hook.ts index d1a806bfe..2ea7cda84 100644 --- a/tokens/token-2022/transfer-hook/transfer-cost/anchor/tests/transfer-hook.ts +++ b/tokens/token-2022/transfer-hook/transfer-cost/anchor/tests/transfer-hook.ts @@ -1,6 +1,6 @@ -import assert from 'node:assert'; -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; +import assert from "node:assert"; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; import { ASSOCIATED_TOKEN_PROGRAM_ID, createApproveInstruction, @@ -22,11 +22,11 @@ import { NATIVE_MINT, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, -} from '@solana/spl-token'; -import { Keypair, PublicKey, SystemProgram, sendAndConfirmTransaction, Transaction } from '@solana/web3.js'; -import type { TransferHook } from '../target/types/transfer_hook'; +} from "@solana/spl-token"; +import { Keypair, PublicKey, SystemProgram, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; +import type { TransferHook } from "../target/types/transfer_hook"; -describe('transfer-hook', () => { +describe("transfer-hook", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); @@ -59,7 +59,7 @@ describe('transfer-hook', () => { ); // PDA delegate to transfer wSOL tokens from sender - const [delegatePDA] = PublicKey.findProgramAddressSync([Buffer.from('delegate')], program.programId); + const [delegatePDA] = PublicKey.findProgramAddressSync([Buffer.from("delegate")], program.programId); // Sender wSOL token account address const senderWSolTokenAccount = getAssociatedTokenAddressSync( @@ -83,7 +83,7 @@ describe('transfer-hook', () => { await getOrCreateAssociatedTokenAccount(connection, wallet.payer, NATIVE_MINT, delegatePDA, true); }); - it('Create Mint Account with Transfer Hook Extension', async () => { + it("Create Mint Account with Transfer Hook Extension", async () => { const extensions = [ExtensionType.TransferHook]; const mintLen = getMintLen(extensions); const lamports = await provider.connection.getMinimumBalanceForRentExemption(mintLen); @@ -111,7 +111,7 @@ describe('transfer-hook', () => { // Create the two token accounts for the transfer-hook enabled mint // Fund the sender token account with 100 tokens - it('Create Token Accounts and Mint Tokens', async () => { + it("Create Token Accounts and Mint Tokens", async () => { // 100 tokens const amount = 100 * 10 ** decimals; @@ -141,7 +141,7 @@ describe('transfer-hook', () => { }); // Account to store extra accounts required by the transfer hook instruction - it('Create ExtraAccountMetaList Account', async () => { + it("Create ExtraAccountMetaList Account", async () => { const initializeExtraAccountMetaListInstruction = await program.methods .initializeExtraAccountMetaList() .accounts({ @@ -152,11 +152,14 @@ describe('transfer-hook', () => { const transaction = new Transaction().add(initializeExtraAccountMetaListInstruction); - const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { skipPreflight: true, commitment: 'confirmed' }); - console.log('Transaction Signature:', txSig); + const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { + skipPreflight: true, + commitment: "confirmed", + }); + console.log("Transaction Signature:", txSig); }); - it('Transfer Hook with Extra Account Meta', async () => { + it("Transfer Hook with Extra Account Meta", async () => { // 1 tokens const amount = 1 * 10 ** decimals; const bigIntAmount = BigInt(amount); @@ -169,19 +172,26 @@ describe('transfer-hook', () => { }); // Approve delegate PDA to transfer WSol tokens from sender WSol token account - const approveInstruction = createApproveInstruction(senderWSolTokenAccount, delegatePDA, wallet.publicKey, amount, [], TOKEN_PROGRAM_ID); + const approveInstruction = createApproveInstruction( + senderWSolTokenAccount, + delegatePDA, + wallet.publicKey, + amount, + [], + TOKEN_PROGRAM_ID, + ); // Sync sender WSol token account const syncWrappedSolInstruction = createSyncNativeInstruction(senderWSolTokenAccount); - const mintInfo = await getMint(connection, mint.publicKey, 'confirmed', TOKEN_2022_PROGRAM_ID); + const mintInfo = await getMint(connection, mint.publicKey, "confirmed", TOKEN_2022_PROGRAM_ID); const transferHook = getTransferHook(mintInfo); if (transferHook != null) { console.log(`Transfer hook program found: ${JSON.stringify(transferHook, null, 2)}`); } const extraAccountsAccount = getExtraAccountMetaAddress(mint.publicKey, transferHook.programId); - const extraAccountsInfo = await connection.getAccountInfo(extraAccountsAccount, 'confirmed'); + const extraAccountsInfo = await connection.getAccountInfo(extraAccountsAccount, "confirmed"); const extraAccountMetas = getExtraAccountMetas(extraAccountsInfo); for (const extraAccountMeta of extraAccountMetas) { @@ -198,16 +208,21 @@ describe('transfer-hook', () => { bigIntAmount, decimals, [], - 'confirmed', + "confirmed", TOKEN_2022_PROGRAM_ID, ); - console.log('Pushed keys:', JSON.stringify(transferInstruction.keys, null, 2)); + console.log("Pushed keys:", JSON.stringify(transferInstruction.keys, null, 2)); - const transaction = new Transaction().add(solTransferInstruction, syncWrappedSolInstruction, approveInstruction, transferInstruction); + const transaction = new Transaction().add( + solTransferInstruction, + syncWrappedSolInstruction, + approveInstruction, + transferInstruction, + ); const txSig = await sendAndConfirmTransaction(connection, transaction, [wallet.payer], { skipPreflight: true }); - console.log('Transfer Signature:', txSig); + console.log("Transfer Signature:", txSig); const tokenAccount = await getAccount(connection, delegateWSolTokenAccount); diff --git a/tokens/token-2022/transfer-hook/transfer-switch/anchor/Anchor.toml b/tokens/token-2022/transfer-hook/transfer-switch/anchor/Anchor.toml index b0c291690..988def122 100644 --- a/tokens/token-2022/transfer-hook/transfer-switch/anchor/Anchor.toml +++ b/tokens/token-2022/transfer-hook/transfer-switch/anchor/Anchor.toml @@ -6,13 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -transfer_switch = "FjcHckEgXcBhFmSGai3FRpDLiT6hbpV893n8iTxVd81g" - -# [registry] section removed — no longer used in Anchor 1.0 +transfer_switch = "H4LiorjbDr33X1KkTkWX9Eqy345uQH5HGNsxcPoXfGCg" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-2022/transfer-hook/transfer-switch/anchor/package.json b/tokens/token-2022/transfer-hook/transfer-switch/anchor/package.json index e65993ea8..37d84112c 100644 --- a/tokens/token-2022/transfer-hook/transfer-switch/anchor/package.json +++ b/tokens/token-2022/transfer-hook/transfer-switch/anchor/package.json @@ -1,19 +1,19 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "10.0.9", - "anchor-bankrun": "^0.5.0", - "chai": "^4.3.4", - "mocha": "^10.8.2", - "prettier": "^2.6.2", - "solana-bankrun": "^0.4.0", - "ts-mocha": "^10.0.0", - "typescript": "^5" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "10.0.9", + "anchor-bankrun": "^0.5.0", + "chai": "^4.3.4", + "mocha": "^10.8.2", + "prettier": "^2.6.2", + "solana-bankrun": "^0.4.0", + "ts-mocha": "^10.0.0", + "typescript": "^5" + } } diff --git a/tokens/token-2022/transfer-hook/transfer-switch/anchor/pnpm-lock.yaml b/tokens/token-2022/transfer-hook/transfer-switch/anchor/pnpm-lock.yaml index 9a8c97edf..ab332d5ba 100644 --- a/tokens/token-2022/transfer-hook/transfer-switch/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/transfer-hook/transfer-switch/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.0 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -48,18 +48,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -893,16 +893,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.6.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -920,7 +920,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/Cargo.toml b/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/Cargo.toml index c3dc99a39..2cf6c344e 100644 --- a/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/Cargo.toml +++ b/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/Cargo.toml @@ -20,12 +20,18 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } -anchor-spl = "1.0.0-rc.5" +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = "1.0.0" spl-discriminator = "0.4.1" spl-tlv-account-resolution = "0.9.0" spl-transfer-hook-interface = "0.9.0" +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/src/lib.rs b/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/src/lib.rs index 358558a06..9a025b457 100644 --- a/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/src/lib.rs +++ b/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/src/lib.rs @@ -9,7 +9,7 @@ use spl_transfer_hook_interface::instruction::{ ExecuteInstruction, InitializeExtraAccountMetaListInstruction, }; -declare_id!("FjcHckEgXcBhFmSGai3FRpDLiT6hbpV893n8iTxVd81g"); +declare_id!("H4LiorjbDr33X1KkTkWX9Eqy345uQH5HGNsxcPoXfGCg"); #[program] pub mod transfer_switch { diff --git a/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/tests/test_transfer_switch.rs b/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/tests/test_transfer_switch.rs new file mode 100644 index 000000000..a861d913b --- /dev/null +++ b/tokens/token-2022/transfer-hook/transfer-switch/anchor/programs/transfer-switch/tests/test_transfer_switch.rs @@ -0,0 +1,190 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::Instruction, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_account, create_token_extensions_mint, + mint_tokens_to_token_extensions_account, transfer_checked_token_extensions, + MintExtension, TOKEN_EXTENSIONS_PROGRAM_ID, + }, + transfer_hook::{build_hook_accounts, get_hook_accounts_address, HookAccount}, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = transfer_switch::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/transfer_switch.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_transfer_switch() { + let (mut svm, program_id, payer) = setup(); + let sender = create_wallet(&mut svm, 10_000_000_000).unwrap(); + let recipient = Keypair::new(); + let decimals: u8 = 9; + + // Derive PDAs + let (admin_config, _) = Pubkey::find_program_address(&[b"admin-config"], &program_id); + let (sender_switch, _) = + Pubkey::find_program_address(&[sender.pubkey().as_ref()], &program_id); + + // Step 1: Create mint with TransferHook extension + let mint = create_token_extensions_mint( + &mut svm, + &payer, + decimals, + None, + &[MintExtension::TransferHook { + program_id: program_id, + }], + ) + .unwrap(); + svm.expire_blockhash(); + + let extra_account_meta_list = + get_hook_accounts_address(&mint, &program_id); + + // Step 2: Create token accounts and mint tokens + let amount: u64 = 100 * 10u64.pow(decimals as u32); + let source_ata = create_token_extensions_account( + &mut svm, + &sender.pubkey(), + &mint, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + let dest_ata = create_token_extensions_account( + &mut svm, + &recipient.pubkey(), + &mint, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + mint_tokens_to_token_extensions_account( + &mut svm, + &mint, + &source_ata, + amount, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 3: Configure admin + let configure_admin_ix = Instruction::new_with_bytes( + program_id, + &transfer_switch::instruction::ConfigureAdmin {}.data(), + transfer_switch::accounts::ConfigureAdmin { + admin: payer.pubkey(), + new_admin: payer.pubkey(), + admin_config, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![configure_admin_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 4: Initialize extra account metas list + let init_extra_ix = Instruction::new_with_bytes( + program_id, + &transfer_switch::instruction::InitializeExtraAccountMetasList {}.data(), + transfer_switch::accounts::InitializeExtraAccountMetas { + payer: payer.pubkey(), + token_mint: mint, + extra_account_metas_list: extra_account_meta_list, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_extra_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 5: Turn transfers OFF for sender + let switch_off_ix = Instruction::new_with_bytes( + program_id, + &transfer_switch::instruction::Switch { on: false }.data(), + transfer_switch::accounts::Switch { + admin: payer.pubkey(), + wallet: sender.pubkey(), + admin_config, + wallet_switch: sender_switch, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![switch_off_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 6: Try transfer — should FAIL (switch is off) + let transfer_amount: u64 = 1 * 10u64.pow(decimals as u32); + let extra_accounts = build_hook_accounts( + &mint, + &program_id, + &[HookAccount { + pubkey: sender_switch, + is_signer: false, + is_writable: false, + }], + ); + let result = transfer_checked_token_extensions( + &mut svm, + &source_ata, + &mint, + &dest_ata, + &sender, + transfer_amount, + decimals, + &extra_accounts, + ); + assert!( + result.is_err(), + "Transfer should fail when switch is off" + ); + svm.expire_blockhash(); + + // Step 7: Turn transfers ON for sender + let switch_on_ix = Instruction::new_with_bytes( + program_id, + &transfer_switch::instruction::Switch { on: true }.data(), + transfer_switch::accounts::Switch { + admin: payer.pubkey(), + wallet: sender.pubkey(), + admin_config, + wallet_switch: sender_switch, + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![switch_on_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 8: Transfer — should SUCCEED (switch is on) + transfer_checked_token_extensions( + &mut svm, + &source_ata, + &mint, + &dest_ata, + &sender, + transfer_amount, + decimals, + &extra_accounts, + ).unwrap(); +} diff --git a/tokens/token-2022/transfer-hook/transfer-switch/anchor/tests/transfer-switch.ts b/tokens/token-2022/transfer-hook/transfer-switch/anchor/tests/transfer-switch.ts index 85969836f..f762a429a 100644 --- a/tokens/token-2022/transfer-hook/transfer-switch/anchor/tests/transfer-switch.ts +++ b/tokens/token-2022/transfer-hook/transfer-switch/anchor/tests/transfer-switch.ts @@ -13,21 +13,16 @@ import { getMintLen, TOKEN_2022_PROGRAM_ID, } from "@solana/spl-token"; -import { - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from "@solana/web3.js"; +import { Keypair, PublicKey, SystemProgram, Transaction, type TransactionInstruction } from "@solana/web3.js"; import { BankrunProvider } from "anchor-bankrun"; import { assert } from "chai"; import { startAnchor } from "solana-bankrun"; +import IDL from "../target/idl/transfer_switch.json"; import type { TransferSwitch } from "../target/types/transfer_switch"; -import IDL from "../target/idl/transfer_switch.json"; const PROGRAM_ID = new PublicKey(IDL.address); +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 const expectRevert = async (promise: Promise) => { try { await promise; @@ -38,11 +33,7 @@ const expectRevert = async (promise: Promise) => { }; describe("Transfer switch", async () => { - const context = await startAnchor( - "", - [{ name: "transfer_switch", programId: PROGRAM_ID }], - [], - ); + const context = await startAnchor("", [{ name: "transfer_switch", programId: PROGRAM_ID }], []); const provider = new BankrunProvider(context); const _wallet = provider.wallet as anchor.Wallet; @@ -77,10 +68,7 @@ describe("Transfer switch", async () => { } // admin config address - const adminConfigAddress = PublicKey.findProgramAddressSync( - [Buffer.from("admin-config")], - PROGRAM_ID, - )[0]; + const adminConfigAddress = PublicKey.findProgramAddressSync([Buffer.from("admin-config")], PROGRAM_ID)[0]; // helper for getting wallet switch const walletTransferSwitchAddress = (wallet: PublicKey) => @@ -92,8 +80,7 @@ describe("Transfer switch", async () => { it("Create Mint Account with Transfer Hook Extension", async () => { const extensions = [ExtensionType.TransferHook]; const mintLen = getMintLen(extensions); - const lamports = - await provider.connection.getMinimumBalanceForRentExemption(mintLen); + const lamports = await provider.connection.getMinimumBalanceForRentExemption(mintLen); const transaction = new Transaction().add( SystemProgram.createAccount({ @@ -109,13 +96,7 @@ describe("Transfer switch", async () => { program.programId, // Transfer Hook Program ID TOKEN_2022_PROGRAM_ID, ), - createInitializeMintInstruction( - mint.publicKey, - decimals, - payer.publicKey, - null, - TOKEN_2022_PROGRAM_ID, - ), + createInitializeMintInstruction(mint.publicKey, decimals, payer.publicKey, null, TOKEN_2022_PROGRAM_ID), ); transaction.recentBlockhash = context.lastBlockhash; @@ -132,14 +113,7 @@ describe("Transfer switch", async () => { const transaction = new Transaction().add( senderTokenAccountCreateIx, // create sender token account - createMintToInstruction( - mint.publicKey, - senderTokenAccount, - payer.publicKey, - amount, - [], - TOKEN_2022_PROGRAM_ID, - ), + createMintToInstruction(mint.publicKey, senderTokenAccount, payer.publicKey, amount, [], TOKEN_2022_PROGRAM_ID), ); transaction.recentBlockhash = context.lastBlockhash; @@ -173,13 +147,9 @@ describe("Transfer switch", async () => { .signers([payer]) .rpc(); - const adminConfig = - await program.account.adminConfig.fetch(adminConfigAddress); + const adminConfig = await program.account.adminConfig.fetch(adminConfigAddress); assert(adminConfig.isInitialised === true, "admin config not initialised"); - assert( - adminConfig.admin.toBase58() === payer.publicKey.toBase58(), - "admin does not match", - ); + assert(adminConfig.admin.toBase58() === payer.publicKey.toBase58(), "admin does not match"); }); // Account to store extra accounts required by the transfer hook instruction @@ -193,14 +163,9 @@ describe("Transfer switch", async () => { .signers([payer]) .rpc(); - const walletSwitch = await program.account.transferSwitch.fetch( - walletTransferSwitchAddress(sender.publicKey), - ); + const walletSwitch = await program.account.transferSwitch.fetch(walletTransferSwitchAddress(sender.publicKey)); - assert( - walletSwitch.wallet.toBase58() === sender.publicKey.toBase58(), - "wallet key does not match", - ); + assert(walletSwitch.wallet.toBase58() === sender.publicKey.toBase58(), "wallet key does not match"); assert(!walletSwitch.on, "wallet switch not set to false"); }); @@ -209,8 +174,7 @@ describe("Transfer switch", async () => { const amount = 1 * 10 ** decimals; const bigIntAmount = BigInt(amount); - const [recipient, recipientTokenAccount, recipientTokenAccountCreateIx] = - newUser(); + const [recipient, recipientTokenAccount, recipientTokenAccountCreateIx] = newUser(); // create the recipient token account ahead of the transfer, // @@ -224,19 +188,18 @@ describe("Transfer switch", async () => { client.processTransaction(transaction); // Standard token transfer instruction - const transferInstruction = - await createTransferCheckedWithTransferHookInstruction( - connection, - senderTokenAccount, - mint.publicKey, - recipientTokenAccount, - sender.publicKey, - bigIntAmount, - decimals, - [], - "confirmed", - TOKEN_2022_PROGRAM_ID, - ); + const transferInstruction = await createTransferCheckedWithTransferHookInstruction( + connection, + senderTokenAccount, + mint.publicKey, + recipientTokenAccount, + sender.publicKey, + bigIntAmount, + decimals, + [], + "confirmed", + TOKEN_2022_PROGRAM_ID, + ); transaction = new Transaction().add( transferInstruction, // transfer instruction @@ -249,12 +212,8 @@ describe("Transfer switch", async () => { // expectRevert(client.processTransaction(transaction)); - const recipientTokenAccountData = ( - await client.getAccount(recipientTokenAccount) - ).data; - const recipientBalance = AccountLayout.decode( - recipientTokenAccountData, - ).amount; + const recipientTokenAccountData = (await client.getAccount(recipientTokenAccount)).data; + const recipientBalance = AccountLayout.decode(recipientTokenAccountData).amount; assert(recipientBalance === BigInt(0), "transfer was successful"); }); @@ -270,14 +229,9 @@ describe("Transfer switch", async () => { .signers([payer]) .rpc(); - const walletSwitch = await program.account.transferSwitch.fetch( - walletTransferSwitchAddress(sender.publicKey), - ); + const walletSwitch = await program.account.transferSwitch.fetch(walletTransferSwitchAddress(sender.publicKey)); - assert( - walletSwitch.wallet.toBase58() === sender.publicKey.toBase58(), - "wallet key does not match", - ); + assert(walletSwitch.wallet.toBase58() === sender.publicKey.toBase58(), "wallet key does not match"); assert(walletSwitch.on, "wallet switch not set to true"); }); @@ -286,41 +240,32 @@ describe("Transfer switch", async () => { const amount = 1 * 10 ** decimals; const bigIntAmount = BigInt(amount); - const [_recipient, recipientTokenAccount, recipientTokenAccountCreateIx] = - newUser(); + const [_recipient, recipientTokenAccount, recipientTokenAccountCreateIx] = newUser(); // Standard token transfer instruction - const transferInstruction = - await createTransferCheckedWithTransferHookInstruction( - connection, - senderTokenAccount, - mint.publicKey, - recipientTokenAccount, - sender.publicKey, - bigIntAmount, - decimals, - [], - "confirmed", - TOKEN_2022_PROGRAM_ID, - ); - - const transaction = new Transaction().add( - recipientTokenAccountCreateIx, - transferInstruction, + const transferInstruction = await createTransferCheckedWithTransferHookInstruction( + connection, + senderTokenAccount, + mint.publicKey, + recipientTokenAccount, + sender.publicKey, + bigIntAmount, + decimals, + [], + "confirmed", + TOKEN_2022_PROGRAM_ID, ); + const transaction = new Transaction().add(recipientTokenAccountCreateIx, transferInstruction); + transaction.recentBlockhash = context.lastBlockhash; transaction.sign(payer, sender); await client.processTransaction(transaction); - const recipientTokenAccountData = ( - await client.getAccount(recipientTokenAccount) - ).data; + const recipientTokenAccountData = (await client.getAccount(recipientTokenAccount)).data; - const recipientBalance = AccountLayout.decode( - recipientTokenAccountData, - ).amount; + const recipientBalance = AccountLayout.decode(recipientTokenAccountData).amount; assert(recipientBalance === bigIntAmount, "transfer was not successful"); }); diff --git a/tokens/token-2022/transfer-hook/whitelist/anchor/Anchor.toml b/tokens/token-2022/transfer-hook/whitelist/anchor/Anchor.toml index 356cfec90..982f03943 100644 --- a/tokens/token-2022/transfer-hook/whitelist/anchor/Anchor.toml +++ b/tokens/token-2022/transfer-hook/whitelist/anchor/Anchor.toml @@ -2,22 +2,17 @@ solana_version = "3.1.8" [features] -seeds = false +resolution = true skip-lint = false [programs.localnet] -transfer_hook = "DrWbQtYJGtsoRwzKqAbHKHKsCJJfpysudF39GBVFSxub" - -# [registry] section removed — no longer used in Anchor 1.0 +transfer_hook = "Gkhsnn4Svph2FUNKbNHXQiKHpXWv6xfUBxitSxs7EzW2" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" -# Transfer-hook tests use the real local validator (not bankrun). -# No external program clones needed — this project doesn't use Metaplex. -# The previous [[test.validator.clone]] of metaplex was unnecessary and -# caused 5-minute timeouts in CI trying to fetch from devnet. +[hooks] diff --git a/tokens/token-2022/transfer-hook/whitelist/anchor/migrations/deploy.ts b/tokens/token-2022/transfer-hook/whitelist/anchor/migrations/deploy.ts index cfcedbc47..81b3ef439 100644 --- a/tokens/token-2022/transfer-hook/whitelist/anchor/migrations/deploy.ts +++ b/tokens/token-2022/transfer-hook/whitelist/anchor/migrations/deploy.ts @@ -2,7 +2,7 @@ // single deploy script that's invoked from the CLI, injecting a provider // configured from the workspace's Anchor.toml. -const anchor = require('@anchor-lang/core'); +const anchor = require("@anchor-lang/core"); module.exports = async (provider) => { // Configure client to use the provider. diff --git a/tokens/token-2022/transfer-hook/whitelist/anchor/package.json b/tokens/token-2022/transfer-hook/whitelist/anchor/package.json index 908f2ae4d..79d498c2a 100644 --- a/tokens/token-2022/transfer-hook/whitelist/anchor/package.json +++ b/tokens/token-2022/transfer-hook/whitelist/anchor/package.json @@ -1,23 +1,23 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.0" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/chai-as-promised": "^7.1.8", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.2", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/chai-as-promised": "^7.1.8", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "chai-as-promised": "^7.1.2", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-2022/transfer-hook/whitelist/anchor/pnpm-lock.yaml b/tokens/token-2022/transfer-hook/whitelist/anchor/pnpm-lock.yaml index 8bd73a769..1c8575404 100644 --- a/tokens/token-2022/transfer-hook/whitelist/anchor/pnpm-lock.yaml +++ b/tokens/token-2022/transfer-hook/whitelist/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.0 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -48,18 +48,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -874,16 +874,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -901,7 +901,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/Cargo.toml b/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/Cargo.toml index cf9678574..24e07e0b6 100644 --- a/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/Cargo.toml +++ b/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/Cargo.toml @@ -20,12 +20,18 @@ custom-heap = [] custom-panic = [] [dependencies] -# Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } -anchor-spl = "1.0.0-rc.5" +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = "1.0.0" spl-discriminator = "0.4.1" spl-tlv-account-resolution = "0.9.0" spl-transfer-hook-interface = "0.9.0" +[dev-dependencies] +litesvm = "0.11.0" +solana-kite = "0.3.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +borsh = "1.6.1" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/src/lib.rs b/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/src/lib.rs index 5ac0f64c3..ab155381b 100644 --- a/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/src/lib.rs +++ b/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/src/lib.rs @@ -19,7 +19,7 @@ use spl_transfer_hook_interface::instruction::{ ExecuteInstruction, InitializeExtraAccountMetaListInstruction, }; -declare_id!("DrWbQtYJGtsoRwzKqAbHKHKsCJJfpysudF39GBVFSxub"); +declare_id!("Gkhsnn4Svph2FUNKbNHXQiKHpXWv6xfUBxitSxs7EzW2"); #[error_code] pub enum TransferError { diff --git a/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/tests/test_transfer_hook.rs b/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/tests/test_transfer_hook.rs new file mode 100644 index 000000000..35152fa76 --- /dev/null +++ b/tokens/token-2022/transfer-hook/whitelist/anchor/programs/transfer-hook/tests/test_transfer_hook.rs @@ -0,0 +1,138 @@ +use { + anchor_lang::{ + solana_program::{ + instruction::Instruction, + pubkey::Pubkey, + system_program, + }, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_kite::{ + create_wallet, send_transaction_from_instructions, + token_extensions::{ + create_token_extensions_account, create_token_extensions_mint, + mint_tokens_to_token_extensions_account, transfer_checked_token_extensions, + MintExtension, TOKEN_EXTENSIONS_PROGRAM_ID, + }, + transfer_hook::{build_hook_accounts, get_hook_accounts_address, HookAccount}, + }, + solana_keypair::Keypair, + solana_signer::Signer, +}; + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = transfer_hook::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/transfer_hook.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_whitelist_transfer_hook() { + let (mut svm, program_id, payer) = setup(); + let recipient = Keypair::new(); + let decimals: u8 = 9; + + // Derive PDAs + let (white_list_pda, _) = Pubkey::find_program_address(&[b"white_list"], &program_id); + + // Step 1: Create mint with TransferHook extension + let mint = create_token_extensions_mint( + &mut svm, + &payer, + decimals, + None, + &[MintExtension::TransferHook { + program_id: program_id, + }], + ) + .unwrap(); + svm.expire_blockhash(); + + let extra_account_meta_list = + get_hook_accounts_address(&mint, &program_id); + + // Step 2: Create token accounts and mint tokens + let amount: u64 = 100 * 10u64.pow(decimals as u32); + let source_ata = create_token_extensions_account( + &mut svm, + &payer.pubkey(), + &mint, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + let dest_ata = create_token_extensions_account( + &mut svm, + &recipient.pubkey(), + &mint, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + mint_tokens_to_token_extensions_account( + &mut svm, + &mint, + &source_ata, + amount, + &payer, + ).unwrap(); + svm.expire_blockhash(); + + // Step 3: Initialize ExtraAccountMetaList (also creates whitelist) + let init_extra_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::InitializeExtraAccountMetaList {}.data(), + transfer_hook::accounts::InitializeExtraAccountMetaList { + payer: payer.pubkey(), + extra_account_meta_list, + mint, + system_program: system_program::id(), + white_list: white_list_pda, + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![init_extra_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 4: Add destination token account to whitelist + let add_to_whitelist_ix = Instruction::new_with_bytes( + program_id, + &transfer_hook::instruction::AddToWhitelist {}.data(), + transfer_hook::accounts::AddToWhiteList { + new_account: dest_ata, + white_list: white_list_pda, + signer: payer.pubkey(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions(&mut svm, vec![add_to_whitelist_ix], &[&payer], &payer.pubkey()).unwrap(); + svm.expire_blockhash(); + + // Step 5: Transfer — should succeed (destination is whitelisted) + let transfer_amount: u64 = 1 * 10u64.pow(decimals as u32); + let extra_accounts = build_hook_accounts( + &mint, + &program_id, + &[HookAccount { + pubkey: white_list_pda, + is_signer: false, + is_writable: true, + }], + ); + transfer_checked_token_extensions( + &mut svm, + &source_ata, + &mint, + &dest_ata, + &payer, + transfer_amount, + decimals, + &extra_accounts, + ).unwrap(); +} diff --git a/tokens/token-2022/transfer-hook/whitelist/anchor/tests/transfer-hook.ts b/tokens/token-2022/transfer-hook/whitelist/anchor/tests/transfer-hook.ts index 3dd06a21c..70d2bdcbb 100644 --- a/tokens/token-2022/transfer-hook/whitelist/anchor/tests/transfer-hook.ts +++ b/tokens/token-2022/transfer-hook/whitelist/anchor/tests/transfer-hook.ts @@ -1,5 +1,5 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; import { ASSOCIATED_TOKEN_PROGRAM_ID, createAssociatedTokenAccountInstruction, @@ -11,11 +11,11 @@ import { getAssociatedTokenAddressSync, getMintLen, TOKEN_2022_PROGRAM_ID, -} from '@solana/spl-token'; -import { Keypair, SystemProgram, sendAndConfirmTransaction, Transaction } from '@solana/web3.js'; -import type { TransferHook } from '../target/types/transfer_hook'; +} from "@solana/spl-token"; +import { Keypair, SystemProgram, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; +import type { TransferHook } from "../target/types/transfer_hook"; -describe('transfer-hook', () => { +describe("transfer-hook", () => { // Configure the client to use the local cluster. const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); @@ -47,7 +47,7 @@ describe('transfer-hook', () => { ASSOCIATED_TOKEN_PROGRAM_ID, ); - it('Create Mint Account with Transfer Hook Extension', async () => { + it("Create Mint Account with Transfer Hook Extension", async () => { const extensions = [ExtensionType.TransferHook]; const mintLen = getMintLen(extensions); const lamports = await provider.connection.getMinimumBalanceForRentExemption(mintLen); @@ -75,7 +75,7 @@ describe('transfer-hook', () => { // Create the two token accounts for the transfer-hook enabled mint // Fund the sender token account with 100 tokens - it('Create Token Accounts and Mint Tokens', async () => { + it("Create Token Accounts and Mint Tokens", async () => { // 100 tokens const amount = 100 * 10 ** decimals; @@ -105,7 +105,7 @@ describe('transfer-hook', () => { }); // Account to store extra accounts required by the transfer hook instruction - it('Create ExtraAccountMetaList Account', async () => { + it("Create ExtraAccountMetaList Account", async () => { const initializeExtraAccountMetaListInstruction = await program.methods .initializeExtraAccountMetaList() .accounts({ @@ -115,12 +115,15 @@ describe('transfer-hook', () => { const transaction = new Transaction().add(initializeExtraAccountMetaListInstruction); - const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { skipPreflight: true, commitment: 'confirmed' }); + const txSig = await sendAndConfirmTransaction(provider.connection, transaction, [wallet.payer], { + skipPreflight: true, + commitment: "confirmed", + }); - console.log('Transaction Signature:', txSig); + console.log("Transaction Signature:", txSig); }); - it('Add account to white list', async () => { + it("Add account to white list", async () => { const addAccountToWhiteListInstruction = await program.methods .addToWhitelist() .accounts({ @@ -132,10 +135,10 @@ describe('transfer-hook', () => { const transaction = new Transaction().add(addAccountToWhiteListInstruction); const txSig = await sendAndConfirmTransaction(connection, transaction, [wallet.payer], { skipPreflight: true }); - console.log('White Listed:', txSig); + console.log("White Listed:", txSig); }); - it('Transfer Hook with Extra Account Meta', async () => { + it("Transfer Hook with Extra Account Meta", async () => { // 1 tokens const amount = 1 * 10 ** decimals; const bigIntAmount = BigInt(amount); @@ -150,13 +153,13 @@ describe('transfer-hook', () => { bigIntAmount, decimals, [], - 'confirmed', + "confirmed", TOKEN_2022_PROGRAM_ID, ); const transaction = new Transaction().add(transferInstruction); const txSig = await sendAndConfirmTransaction(connection, transaction, [wallet.payer], { skipPreflight: true }); - console.log('Transfer Checked:', txSig); + console.log("Transfer Checked:", txSig); }); }); diff --git a/tokens/token-fundraiser/anchor/Anchor.toml b/tokens/token-fundraiser/anchor/Anchor.toml index 237dbed3c..d4a75652c 100644 --- a/tokens/token-fundraiser/anchor/Anchor.toml +++ b/tokens/token-fundraiser/anchor/Anchor.toml @@ -5,17 +5,17 @@ solana_version = "3.1.8" resolution = true skip-lint = false -[programs.localnet] -fundraiser = "Eoiuq1dXvHxh6dLx3wh9gj8kSAUpga11krTrbfF5XYsC" - [programs.devnet] fundraiser = "Eoiuq1dXvHxh6dLx3wh9gj8kSAUpga11krTrbfF5XYsC" -# [registry] section removed — no longer used in Anchor 1.0 +[programs.localnet] +fundraiser = "EuqudshRf8VRskatC6U3txgivHmtCkY5d1qsK5B3VAio" [provider] -cluster = "Localnet" +cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/token-fundraiser/anchor/Cargo.lock b/tokens/token-fundraiser/anchor/Cargo.lock index 2c19ef810..662ae9869 100644 --- a/tokens/token-fundraiser/anchor/Cargo.lock +++ b/tokens/token-fundraiser/anchor/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "generic-array", ] @@ -20,7 +20,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -38,20 +38,107 @@ dependencies = [ "zeroize", ] +[[package]] +name = "agave-feature-set" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e631ba26aeffe98dee3db0b8612fc7c67cda71bc57b0f82f28dc48231df6bc8" +dependencies = [ + "ahash", + "solana-epoch-schedule", + "solana-hash 3.1.0", + "solana-pubkey 3.0.0", + "solana-sha256-hasher", + "solana-svm-feature-set", +] + +[[package]] +name = "agave-reserved-account-keys" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d062865aedfbdc7511726d47e472687db0db4fb08e3c3ab2ac68570106c2f1b6" +dependencies = [ + "agave-feature-set", + "solana-pubkey 3.0.0", + "solana-sdk-ids", +] + +[[package]] +name = "agave-syscalls" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c89f228e93d1bc769578efd0c5a445715ae04ad96f9b6f8d16d018ad7f9221a" +dependencies = [ + "bincode", + "libsecp256k1", + "num-traits", + "solana-account", + "solana-account-info", + "solana-big-mod-exp", + "solana-blake3-hasher", + "solana-bn254", + "solana-clock", + "solana-cpi", + "solana-curve25519", + "solana-hash 3.1.0", + "solana-instruction", + "solana-keccak-hasher", + "solana-loader-v3-interface", + "solana-poseidon", + "solana-program-entrypoint", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sbpf", + "solana-sdk-ids", + "solana-secp256k1-recover", + "solana-sha256-hasher", + "solana-stable-layout", + "solana-stake-interface", + "solana-svm-callback", + "solana-svm-feature-set", + "solana-svm-log-collector", + "solana-svm-measure", + "solana-svm-timings", + "solana-svm-type-overrides", + "solana-sysvar", + "solana-sysvar-id", + "solana-transaction-context", + "thiserror 2.0.18", +] + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anchor-attribute-access-control" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3db7f5f8a6b16fa2b6e1b0222e656249c3abedf052e3943babf248929571204" +checksum = "b972f5fbd02524c92e4eb487c3c648904572702670f3d6fc81aef5f1751b1569" dependencies = [ "proc-macro2", "quote", @@ -60,9 +147,9 @@ dependencies = [ [[package]] name = "anchor-attribute-account" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a12661acaba9866a5f2d8d8d46a1eed8b484f41dc9f94f808c3b07d35726816" +checksum = "9acfcb07a92084bcfa9f6cc49a5c2e8e0e986f25f4b7caa184b7a2c9c9e561c2" dependencies = [ "anchor-syn", "proc-macro2", @@ -72,9 +159,9 @@ dependencies = [ [[package]] name = "anchor-attribute-constant" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dff08bc0187aafc559da8f63b5adeab0bcdf97128765c72dd9a4861f70627fc" +checksum = "8f46cc38f819377f07663b8eb492a701427950065e79d2d7b622a782443deb7a" dependencies = [ "anchor-syn", "quote", @@ -83,9 +170,9 @@ dependencies = [ [[package]] name = "anchor-attribute-error" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2af8ce12fb8cf782a3e127d376698a4548a518e38b4686f9c439adce4730b48" +checksum = "9c34748789107c9838329e058ca7b253e67f37b39ceae5a0a6c8d99f5d1bf1fe" dependencies = [ "anchor-syn", "quote", @@ -94,9 +181,9 @@ dependencies = [ [[package]] name = "anchor-attribute-event" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338be5df076369b99585264aaa46c66229ead67568d61bd38c3ab0fa7a15e554" +checksum = "1a28a3e5eefa03d9c5ef02b2139198f652547d38dddafc9c5545152dfba54556" dependencies = [ "anchor-syn", "proc-macro2", @@ -106,9 +193,9 @@ dependencies = [ [[package]] name = "anchor-attribute-program" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5c4ec70cef4ef7e2d87b4e9c550f727a43d691d3d7f3e4d6b2e3bd530ae098d" +checksum = "dfaa03865053cb168bfc4debe5992be87f397aa027dd81b69a2e44f2e5bae1c5" dependencies = [ "anchor-lang-idl", "anchor-syn", @@ -121,9 +208,9 @@ dependencies = [ [[package]] name = "anchor-derive-accounts" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f610cb50e10e4c404cc774f20a4eb602b904f68ea04590f8b1eb22a1e28b33e5" +checksum = "eef330db08f9ceee45c18ef96b15b869883d280c0ab5c6ff5d2e2f6481da7911" dependencies = [ "anchor-syn", "quote", @@ -132,9 +219,9 @@ dependencies = [ [[package]] name = "anchor-derive-serde" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9ead49a9689493f8857a61dd1abf1d70eeeeb0683f8c1e09b015ab5bdd382d" +checksum = "e0e80ff4e3ddb8c85aafd37926335c28f820516311e7106e5b7482b42e798aaa" dependencies = [ "anchor-syn", "proc-macro-crate", @@ -145,9 +232,9 @@ dependencies = [ [[package]] name = "anchor-derive-space" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4d1372743444967347b60f9311d2ee54a630152fd1d6d805adebd7fcd72056" +checksum = "2672af0ef4dfd5f5b6199355867b580cd8b4048093ef5208dd2b441305c15b8b" dependencies = [ "proc-macro2", "quote", @@ -156,9 +243,9 @@ dependencies = [ [[package]] name = "anchor-lang" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254d0cb160ea5c4c6a8c2f847bbd0f384fef733ebc36ef8426ae95f1bfda5757" +checksum = "8de9dce227fa0c08be20fef008c5b04681e1e0a15cb396e9619a9a1f800ff6cd" dependencies = [ "anchor-attribute-access-control", "anchor-attribute-account", @@ -193,7 +280,7 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-sdk-ids", "solana-stake-interface", - "solana-system-interface", + "solana-system-interface 2.0.0", "solana-sysvar", "solana-sysvar-id", "thiserror 1.0.69", @@ -211,7 +298,7 @@ dependencies = [ "regex", "serde", "serde_json", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -226,9 +313,9 @@ dependencies = [ [[package]] name = "anchor-spl" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3f1da81d6a7486339833833db9285f3771c1c368db418d481b5584a901cd675" +checksum = "300e2e8058e674e8d6ea7c72dfb8be4349609dd9c3760ce729fc6406199624fe" dependencies = [ "anchor-lang", "spl-associated-token-account-interface", @@ -241,9 +328,9 @@ dependencies = [ [[package]] name = "anchor-syn" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a855d34b1b0488f37ccc759c8bd4a696cd3a7bba8cb0734c2a965109f707da" +checksum = "c62f42cb7e348c033bd9bfba59979bcd66431c026ba23490af94045aa357a950" dependencies = [ "anyhow", "bs58", @@ -252,16 +339,266 @@ dependencies = [ "proc-macro2", "quote", "serde", - "sha2", + "sha2 0.10.9", "syn 1.0.109", "thiserror 1.0.69", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-std 0.4.0", +] + +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff 0.4.2", + "ark-poly 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.5", + "itertools 0.13.0", + "num-bigint 0.4.6", + "num-integer", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint 0.4.6", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint 0.4.6", + "num-traits", + "paste", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.5", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive 0.4.2", + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint 0.4.6", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "num-bigint 0.4.6", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ark-std" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", +] [[package]] name = "arrayref" @@ -269,11 +606,35 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ascii" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" + [[package]] name = "autocfg" -version = "1.3.0" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "base64" @@ -287,6 +648,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "bincode" version = "1.3.3" @@ -298,9 +665,33 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.4" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "blake3" +version = "1.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.0", + "digest 0.11.2", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] [[package]] name = "block-buffer" @@ -311,21 +702,31 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "borsh" -version = "1.5.7" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ "borsh-derive", + "bytes", "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "1.5.7" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", "proc-macro-crate", @@ -345,9 +746,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bv" @@ -361,9 +762,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" dependencies = [ "bytemuck_derive", ] @@ -385,6 +786,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + [[package]] name = "cargo_toml" version = "0.19.2" @@ -396,27 +803,67 @@ dependencies = [ ] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "cc" +version = "1.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - +checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + [[package]] name = "cfg_aliases" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "cfg_eval" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "cipher" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", ] +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", +] + [[package]] name = "const-crypto" version = "0.3.0" @@ -427,26 +874,74 @@ dependencies = [ "sha2-const-stable", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +dependencies = [ + "hybrid-array", +] + [[package]] name = "ctr" version = "0.9.2" @@ -456,6 +951,15 @@ dependencies = [ "cipher", ] +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -463,11 +967,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", - "digest", + "digest 0.10.7", "fiat-crypto", - "rand_core", + "rand_core 0.6.4", "rustc_version", "serde", "subtle", @@ -491,8 +995,18 @@ version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -509,45 +1023,227 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + [[package]] name = "darling_macro" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core", + "darling_core 0.21.3", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", "quote", "syn 2.0.117", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "derivation-path" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "const-oid", + "crypto-common 0.1.7", + "subtle", +] + +[[package]] +name = "digest" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.1", + "ctutils", +] + +[[package]] +name = "eager" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe71d579d1812060163dff96056261deb5bf6729b100fa2e36a68b9649ba3d3" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.6.4", + "serde", + "sha2 0.10.9", "subtle", + "zeroize", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "enum-iterator" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd242f399be1da0a5354aa462d57b4ab2b4ee0683cc552f7c007d2d12d36e94" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "feature-probe" @@ -555,12 +1251,28 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "five8" version = "1.0.0" @@ -581,9 +1293,9 @@ dependencies = [ [[package]] name = "five8_core" -version = "0.1.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2551bf44bc5f776c15044b9b94153a00198be06743e262afaaa61f11ac7523a5" +checksum = "059c31d7d36c43fe39d89e55711858b4da8be7eb6dabac23c7289b1a19489406" [[package]] name = "fnv" @@ -597,6 +1309,11 @@ version = "0.1.0" dependencies = [ "anchor-lang", "anchor-spl", + "borsh", + "litesvm", + "solana-keypair", + "solana-kite", + "solana-signer", ] [[package]] @@ -607,21 +1324,83 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", +] + [[package]] name = "hashbrown" version = "0.16.1" @@ -643,7 +1422,16 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", +] + +[[package]] +name = "hybrid-array" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +dependencies = [ + "typenum", ] [[package]] @@ -654,12 +1442,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", ] [[package]] @@ -673,36 +1461,77 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ "once_cell", "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2 0.10.9", + "signature", +] + [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -719,31 +1548,173 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] +name = "libsecp256k1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "light-poseidon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +dependencies = [ + "ark-bn254 0.4.0", + "ark-ff 0.4.2", + "num-bigint 0.4.6", + "thiserror 1.0.69", +] + +[[package]] +name = "light-poseidon" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47a1ccadd0bb5a32c196da536fd72c59183de24a055f6bf0513bf845fefab862" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "num-bigint 0.4.6", + "thiserror 1.0.69", +] + +[[package]] +name = "litesvm" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "347d8c652d592c618ac996f2ab21f8c0b0f2da3fbbca227a6887ee61bb75f2de" +dependencies = [ + "agave-feature-set", + "agave-reserved-account-keys", + "agave-syscalls", + "ansi_term", + "bincode", + "indexmap", + "itertools 0.14.0", + "log", + "serde", + "solana-account", + "solana-address 2.5.0", + "solana-address-lookup-table-interface", + "solana-bpf-loader-program", + "solana-builtins", + "solana-clock", + "solana-compute-budget", + "solana-compute-budget-instruction", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-feature-gate-interface", + "solana-fee", + "solana-fee-structure", + "solana-hash 3.1.0", + "solana-instruction", + "solana-instructions-sysvar", + "solana-keypair", + "solana-last-restart-slot", + "solana-loader-v3-interface", + "solana-loader-v4-interface", + "solana-message", + "solana-native-token", + "solana-nonce", + "solana-nonce-account", + "solana-precompile-error", + "solana-program-error", + "solana-program-runtime", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-sha256-hasher", + "solana-signature", + "solana-signer", + "solana-slot-hashes", + "solana-slot-history", + "solana-stake-interface", + "solana-svm-callback", + "solana-svm-log-collector", + "solana-svm-timings", + "solana-svm-transaction", + "solana-system-interface 2.0.0", + "solana-system-program", + "solana-sysvar", + "solana-sysvar-id", + "solana-transaction", + "solana-transaction-context", + "solana-transaction-error", + "thiserror 2.0.18", +] [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" -version = "2.7.4" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] [[package]] name = "merlin" @@ -753,10 +1724,55 @@ checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ "byteorder", "keccak", - "rand_core", + "rand_core 0.6.4", "zeroize", ] +[[package]] +name = "num" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +dependencies = [ + "num-bigint 0.2.6", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-derive" version = "0.4.2" @@ -768,6 +1784,38 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-bigint 0.2.6", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -801,9 +1849,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "opaque-debug" @@ -813,9 +1861,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -823,17 +1871,23 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-link", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pastey" version = "0.2.1" @@ -846,14 +1900,33 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "percentage" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd23b938276f14057220b707937bcb42fa76dda7560e57a2da30cb52d557937" +dependencies = [ + "num", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] [[package]] name = "polyval" @@ -862,16 +1935,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro-crate" @@ -879,7 +1955,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.8+spec-1.1.0", + "toml_edit 0.25.10+spec-1.1.0", ] [[package]] @@ -900,6 +1976,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "qualifier_attr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "quote" version = "1.0.45" @@ -909,6 +1996,25 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -916,8 +2022,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -927,7 +2053,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -936,23 +2081,41 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -962,9 +2125,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -973,30 +2136,40 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] -name = "rustc_version" +name = "rfc6979" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "semver", + "hmac", + "subtle", ] [[package]] -name = "rustversion" -version = "1.0.17" +name = "rustc-demangle" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] -name = "ryu" -version = "1.0.18" +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "scopeguard" @@ -1005,14 +2178,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "semver" -version = "1.0.23" +name = "sec1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "serde" -version = "1.0.228" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ @@ -1020,13 +2207,23 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + [[package]] name = "serde_bytes" -version = "0.11.15" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -1051,35 +2248,70 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" +dependencies = [ + "serde_core", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" +dependencies = [ + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "sha2" -version = "0.10.8" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", ] [[package]] @@ -1094,15 +2326,49 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest", + "digest 0.10.7", "keccak", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "solana-account" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "efc0ed36decb689413b9da5d57f2be49eea5bebb3cf7897015167b0c4336e731" +dependencies = [ + "bincode", + "serde", + "serde_bytes", + "serde_derive", + "solana-account-info", + "solana-clock", + "solana-instruction-error", + "solana-pubkey 4.1.0", + "solana-sdk-ids", + "solana-sysvar", +] [[package]] name = "solana-account-info" @@ -1110,7 +2376,9 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9cf16495d9eb53e3d04e72366a33bb1c20c24e78c171d8b8f5978357b63ae95" dependencies = [ - "solana-address 2.4.0", + "bincode", + "serde_core", + "solana-address 2.5.0", "solana-program-error", "solana-program-memory", ] @@ -1121,14 +2389,14 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2ecac8e1b7f74c2baa9e774c42817e3e75b20787134b76cc4d45e8a604488f5" dependencies = [ - "solana-address 2.4.0", + "solana-address 2.5.0", ] [[package]] name = "solana-address" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f67735365edc7fb19ed74ec950597107c8ee9cbfebac57b8868b3e78fb6df16" +checksum = "5f08236dacd0e6dc8234becef58e27c8567856644ef509d7e97957d55a91dc72" dependencies = [ "borsh", "bytemuck", @@ -1148,6 +2416,24 @@ dependencies = [ "wincode", ] +[[package]] +name = "solana-address-lookup-table-interface" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e8df0b083c10ce32490410f3795016b1b5d9b4d094658c0a5e496753645b7cd" +dependencies = [ + "bincode", + "bytemuck", + "serde", + "serde_derive", + "solana-clock", + "solana-instruction", + "solana-instruction-error", + "solana-pubkey 4.1.0", + "solana-sdk-ids", + "solana-slot-hashes", +] + [[package]] name = "solana-atomic-u64" version = "3.0.1" @@ -1157,6 +2443,54 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "solana-big-mod-exp" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30c80fb6d791b3925d5ec4bf23a7c169ef5090c013059ec3ed7d0b2c04efa085" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "solana-define-syscall 3.0.0", +] + +[[package]] +name = "solana-bincode" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278a1a5bad62cd9da89ac8d4b7ec444e83caa8ae96aa656dfc27684b28d49a5d" +dependencies = [ + "bincode", + "serde_core", + "solana-instruction-error", +] + +[[package]] +name = "solana-blake3-hasher" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7116e1d942a2432ca3f514625104757ab8a56233787e95144c93950029e31176" +dependencies = [ + "blake3", + "solana-define-syscall 4.0.1", + "solana-hash 4.2.0", +] + +[[package]] +name = "solana-bn254" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ff13a8867fcc7b0f1114764e1bf6191b4551dcaf93729ddc676cd4ec6abc9f" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "bytemuck", + "solana-define-syscall 5.0.0", + "thiserror 2.0.18", +] + [[package]] name = "solana-borsh" version = "3.0.2" @@ -1166,6 +2500,73 @@ dependencies = [ "borsh", ] +[[package]] +name = "solana-bpf-loader-program" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe15f3c804c37fbff5971d34d81d5d2853ae2d03f11947f44f1d10c5b84c9df0" +dependencies = [ + "agave-syscalls", + "bincode", + "qualifier_attr", + "solana-account", + "solana-bincode", + "solana-clock", + "solana-instruction", + "solana-loader-v3-interface", + "solana-loader-v4-interface", + "solana-packet", + "solana-program-entrypoint", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sbpf", + "solana-sdk-ids", + "solana-svm-feature-set", + "solana-svm-log-collector", + "solana-svm-measure", + "solana-svm-type-overrides", + "solana-system-interface 2.0.0", + "solana-transaction-context", +] + +[[package]] +name = "solana-builtins" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d196c19ba1caf61782eba5de053061f298f36d9f2aec57073e2cf27403a926d3" +dependencies = [ + "agave-feature-set", + "solana-bpf-loader-program", + "solana-compute-budget-program", + "solana-hash 3.1.0", + "solana-loader-v4-program", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-system-program", + "solana-vote-program", + "solana-zk-elgamal-proof-program", + "solana-zk-token-proof-program", +] + +[[package]] +name = "solana-builtins-default-costs" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0da4d19885c5ee02d942a9e13354a39ef3ff591ee31d55353070c204ae7b8fed" +dependencies = [ + "agave-feature-set", + "ahash", + "log", + "solana-bpf-loader-program", + "solana-compute-budget-program", + "solana-loader-v4-program", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-system-program", + "solana-vote-program", +] + [[package]] name = "solana-clock" version = "3.0.1" @@ -1179,6 +2580,57 @@ dependencies = [ "solana-sysvar-id", ] +[[package]] +name = "solana-compute-budget" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98426b2f7788c089f4ab840347bff55901e65ceb5d76b850194f0802a733cd4e" +dependencies = [ + "solana-fee-structure", + "solana-program-runtime", +] + +[[package]] +name = "solana-compute-budget-instruction" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb3ea80152fc745fa95d9cd2fc019c3591cdc7598cb4d85a6acdea7a40938f0" +dependencies = [ + "agave-feature-set", + "log", + "solana-borsh", + "solana-builtins-default-costs", + "solana-compute-budget", + "solana-compute-budget-interface", + "solana-instruction", + "solana-packet", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-svm-transaction", + "solana-transaction-error", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-compute-budget-interface" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8292c436b269ad23cecc8b24f7da3ab07ca111661e25e00ce0e1d22771951ab9" +dependencies = [ + "borsh", + "solana-instruction", + "solana-sdk-ids", +] + +[[package]] +name = "solana-compute-budget-program" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688491544a91b94fcb17cffb5cc4dca4be93bc96460fa27325a404c24b584130" +dependencies = [ + "solana-program-runtime", +] + [[package]] name = "solana-cpi" version = "3.1.0" @@ -1244,7 +2696,7 @@ checksum = "f5e7b0ba210593ba8ddd39d6d234d81795d1671cebf3026baa10d5dc23ac42f0" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 4.2.0", "solana-sdk-ids", "solana-sdk-macro", "solana-sysvar-id", @@ -1263,15 +2715,65 @@ dependencies = [ "solana-sysvar-id", ] +[[package]] +name = "solana-epoch-stake" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "027e6d0b9e7daac5b2ac7c3f9ca1b727861121d9ef05084cf435ff736051e7c2" +dependencies = [ + "solana-define-syscall 5.0.0", + "solana-pubkey 4.1.0", +] + +[[package]] +name = "solana-example-mocks" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978855d164845c1b0235d4b4d101cadc55373fffaf0b5b6cfa2194d25b2ed658" +dependencies = [ + "serde", + "serde_derive", + "solana-address-lookup-table-interface", + "solana-clock", + "solana-hash 3.1.0", + "solana-instruction", + "solana-keccak-hasher", + "solana-message", + "solana-nonce", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-system-interface 2.0.0", + "thiserror 2.0.18", +] + [[package]] name = "solana-feature-gate-interface" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75ca9b5cbb6f500f7fd73db5bd95640f71a83f04d6121a0e59a43b202dca2731" dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account", + "solana-account-info", + "solana-instruction", "solana-program-error", "solana-pubkey 4.1.0", + "solana-rent 4.1.0", "solana-sdk-ids", + "solana-system-interface 3.1.0", +] + +[[package]] +name = "solana-fee" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487e4ba57d889e2ecf94a0cac3a3f385fe26d17425aaef3514b79975af2b5d7f" +dependencies = [ + "agave-feature-set", + "solana-fee-structure", + "solana-svm-transaction", ] [[package]] @@ -1285,17 +2787,36 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-fee-structure" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2abdb1223eea8ec64136f39cb1ffcf257e00f915c957c35c0dd9e3f4e700b0" + +[[package]] +name = "solana-hash" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "337c246447142f660f778cf6cb582beba8e28deb05b3b24bfb9ffd7c562e5f41" +dependencies = [ + "solana-hash 4.2.0", +] + [[package]] name = "solana-hash" version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8064ea1d591ec791be95245058ca40f4f5345d390c200069d0f79bbf55bfae55" dependencies = [ + "borsh", "bytemuck", "bytemuck_derive", "five8", "serde", "serde_derive", + "solana-atomic-u64", + "solana-sanitize", + "wincode", ] [[package]] @@ -1305,6 +2826,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97881335fc698deb46c6571945969aae6d93a14e2fff792a368b4fac872f116" dependencies = [ "bincode", + "borsh", "serde", "serde_derive", "solana-define-syscall 5.0.0", @@ -1319,6 +2841,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d3d048edaaeef5a3dc8c01853e585539a74417e4c2d43a9e2c161270045b838" dependencies = [ "num-traits", + "serde", + "serde_derive", "solana-program-error", ] @@ -1354,33 +2878,138 @@ dependencies = [ ] [[package]] -name = "solana-last-restart-slot" -version = "3.0.0" +name = "solana-keccak-hasher" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcda154ec827f5fc1e4da0af3417951b7e9b8157540f81f936c4a8b1156134d0" +checksum = "ed1c0d16d6fdeba12291a1f068cdf0d479d9bff1141bf44afd7aa9d485f65ef8" dependencies = [ - "serde", - "serde_derive", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "sha3", + "solana-define-syscall 4.0.1", + "solana-hash 4.2.0", ] [[package]] -name = "solana-loader-v3-interface" -version = "6.1.0" +name = "solana-keypair" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee44c9b1328c5c712c68966fb8de07b47f3e7bac006e74ddd1bb053d3e46e5d" +checksum = "263d614c12aa267a3278703175fd6440552ca61bc960b5a02a4482720c53438b" dependencies = [ - "serde", - "serde_bytes", - "serde_derive", - "solana-instruction", - "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-system-interface", -] - + "ed25519-dalek", + "five8", + "five8_core", + "rand 0.9.2", + "solana-address 2.5.0", + "solana-seed-phrase", + "solana-signature", + "solana-signer", +] + +[[package]] +name = "solana-kite" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c6774af93647a15b51e266bc76f558fba11fbfbe30131b50664e665a8fea55" +dependencies = [ + "litesvm", + "solana-account", + "solana-instruction", + "solana-keypair", + "solana-message", + "solana-program", + "solana-pubkey 3.0.0", + "solana-signer", + "solana-transaction", + "spl-associated-token-account", + "spl-token", +] + +[[package]] +name = "solana-last-restart-slot" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcda154ec827f5fc1e4da0af3417951b7e9b8157540f81f936c4a8b1156134d0" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-loader-v3-interface" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee44c9b1328c5c712c68966fb8de07b47f3e7bac006e74ddd1bb053d3e46e5d" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-system-interface 2.0.0", +] + +[[package]] +name = "solana-loader-v4-interface" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c948b33ff81fa89699911b207059e493defdba9647eaf18f23abdf3674e0fb" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-system-interface 2.0.0", +] + +[[package]] +name = "solana-loader-v4-program" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b79ecebf56ff8acf46d5c0d77a11e1cb9a0f8eeb6dd1a69d739f3bf8ea8570e" +dependencies = [ + "log", + "solana-account", + "solana-bincode", + "solana-bpf-loader-program", + "solana-instruction", + "solana-loader-v3-interface", + "solana-loader-v4-interface", + "solana-packet", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sbpf", + "solana-sdk-ids", + "solana-svm-log-collector", + "solana-svm-measure", + "solana-svm-type-overrides", + "solana-transaction-context", +] + +[[package]] +name = "solana-message" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0448b1fd891c5f46491e5dc7d9986385ba3c852c340db2911dd29faa01d2b08d" +dependencies = [ + "bincode", + "blake3", + "lazy_static", + "serde", + "serde_derive", + "solana-address 2.5.0", + "solana-hash 4.2.0", + "solana-instruction", + "solana-sanitize", + "solana-sdk-ids", + "solana-short-vec", + "solana-transaction-error", +] + [[package]] name = "solana-msg" version = "3.1.0" @@ -1390,15 +3019,126 @@ dependencies = [ "solana-define-syscall 5.0.0", ] +[[package]] +name = "solana-native-token" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8dd4c280dca9d046139eb5b7a5ac9ad10403fbd64964c7d7571214950d758f" + +[[package]] +name = "solana-nonce" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc469152a63284ef959b80c59cda015262a021da55d3b8fe42171d89c4b64f8" +dependencies = [ + "serde", + "serde_derive", + "solana-fee-calculator", + "solana-hash 4.2.0", + "solana-pubkey 4.1.0", + "solana-sha256-hasher", +] + +[[package]] +name = "solana-nonce-account" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "805fd25b29e5a1a0e6c3dd6320c9da80f275fbe4ff6e392617c303a2085c435e" +dependencies = [ + "solana-account", + "solana-hash 3.1.0", + "solana-nonce", + "solana-sdk-ids", +] + [[package]] name = "solana-nullable" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90429a75d69fdcb31952c3dea79f5f3c8157cfe88221e066103c9c237876073" +checksum = "da028344c595c7416769ff648d206de7962571291a4cea24c38a60b6f40d53bb" dependencies = [ "bytemuck", ] +[[package]] +name = "solana-packet" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edf2f25743c95229ac0fdc32f8f5893ef738dbf332c669e9861d33ddb0f469d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "solana-poseidon" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d213ef5dc664927b43725e9aae1f0848e06d556e7a5f2857f37af9dbf9856c" +dependencies = [ + "ark-bn254 0.4.0", + "ark-bn254 0.5.0", + "light-poseidon 0.2.0", + "light-poseidon 0.4.0", + "solana-define-syscall 3.0.0", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-precompile-error" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cafcd950de74c6c39d55dc8ca108bbb007799842ab370ef26cf45a34453c31e1" +dependencies = [ + "num-traits", +] + +[[package]] +name = "solana-program" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91b12305dd81045d705f427acd0435a2e46444b65367d7179d7bdcfc3bc5f5eb" +dependencies = [ + "memoffset", + "solana-account-info", + "solana-big-mod-exp", + "solana-blake3-hasher", + "solana-borsh", + "solana-clock", + "solana-cpi", + "solana-define-syscall 3.0.0", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-epoch-stake", + "solana-example-mocks", + "solana-fee-calculator", + "solana-hash 3.1.0", + "solana-instruction", + "solana-instruction-error", + "solana-instructions-sysvar", + "solana-keccak-hasher", + "solana-last-restart-slot", + "solana-msg", + "solana-native-token", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-program-option", + "solana-program-pack", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-secp256k1-recover", + "solana-serde-varint", + "solana-serialize-utils", + "solana-sha256-hasher", + "solana-short-vec", + "solana-slot-hashes", + "solana-slot-history", + "solana-stable-layout", + "solana-sysvar", + "solana-sysvar-id", +] + [[package]] name = "solana-program-entrypoint" version = "3.1.1" @@ -1418,6 +3158,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f04fa578707b3612b095f0c8e19b66a1233f7c42ca8082fcb3b745afcc0add6" dependencies = [ "borsh", + "serde", + "serde_derive", ] [[package]] @@ -1444,6 +3186,51 @@ dependencies = [ "solana-program-error", ] +[[package]] +name = "solana-program-runtime" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527e07453b083fa814e35bb56b8aaddb34d20eeeadeb0d13c115780365355c88" +dependencies = [ + "base64 0.22.1", + "bincode", + "itertools 0.12.1", + "log", + "percentage", + "rand 0.8.5", + "serde", + "solana-account", + "solana-account-info", + "solana-clock", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-fee-structure", + "solana-hash 3.1.0", + "solana-instruction", + "solana-last-restart-slot", + "solana-loader-v3-interface", + "solana-program-entrypoint", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sbpf", + "solana-sdk-ids", + "solana-slot-hashes", + "solana-stable-layout", + "solana-stake-interface", + "solana-svm-callback", + "solana-svm-feature-set", + "solana-svm-log-collector", + "solana-svm-measure", + "solana-svm-timings", + "solana-svm-transaction", + "solana-svm-type-overrides", + "solana-system-interface 2.0.0", + "solana-sysvar", + "solana-sysvar-id", + "solana-transaction-context", + "thiserror 2.0.18", +] + [[package]] name = "solana-pubkey" version = "3.0.0" @@ -1459,7 +3246,7 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b06bd918d60111ee1f97de817113e2040ca0cedb740099ee8d646233f6b906c" dependencies = [ - "solana-address 2.4.0", + "solana-address 2.5.0", ] [[package]] @@ -1475,19 +3262,45 @@ dependencies = [ "solana-sysvar-id", ] +[[package]] +name = "solana-rent" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1771d726d4854f1818c750e14aff40b19d84720d0b1b6d53e50e8f16cb6bd62" +dependencies = [ + "solana-sdk-macro", +] + [[package]] name = "solana-sanitize" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf09694a0fc14e5ffb18f9b7b7c0f15ecb6eac5b5610bf76a1853459d19daf9" +[[package]] +name = "solana-sbpf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15b079e08471a9dbfe1e48b2c7439c85aa2a055cbd54eddd8bd257b0a7dbb29" +dependencies = [ + "byteorder", + "combine", + "hash32", + "libc", + "log", + "rand 0.8.5", + "rustc-demangle", + "thiserror 2.0.18", + "winapi", +] + [[package]] name = "solana-sdk-ids" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "def234c1956ff616d46c9dd953f251fa7096ddbaa6d52b165218de97882b7280" dependencies = [ - "solana-address 2.4.0", + "solana-address 2.5.0", ] [[package]] @@ -1502,6 +3315,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "solana-secp256k1-recover" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c5f18893d62e6c73117dcba48f8f5e3266d90e5ec3d0a0a90f9785adac36c1" +dependencies = [ + "k256", + "solana-define-syscall 5.0.0", + "thiserror 2.0.18", +] + [[package]] name = "solana-seed-derivable" version = "3.0.0" @@ -1519,7 +3343,16 @@ checksum = "dc905b200a95f2ea9146e43f2a7181e3aeb55de6bc12afb36462d00a3c7310de" dependencies = [ "hmac", "pbkdf2", - "sha2", + "sha2 0.10.9", +] + +[[package]] +name = "solana-serde-varint" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "950e5b83e839dc0f92c66afc124bb8f40e89bc90f0579e8ec5499296d27f54e3" +dependencies = [ + "serde", ] [[package]] @@ -1539,9 +3372,18 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db7dc3011ea4c0334aaaa7e7128cb390ecf546b28d412e9bf2064680f57f588f" dependencies = [ - "sha2", + "sha2 0.10.9", "solana-define-syscall 4.0.1", - "solana-hash", + "solana-hash 4.2.0", +] + +[[package]] +name = "solana-short-vec" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3bd991c2cc415291c86bb0b6b4d53e93d13bb40344e4c5a2884e0e4f5fa93f" +dependencies = [ + "serde_core", ] [[package]] @@ -1550,8 +3392,13 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "132a93134f1262aa832f1849b83bec6c9945669b866da18661a427943b9e801e" dependencies = [ + "ed25519-dalek", "five8", + "serde", + "serde-big-array", + "serde_derive", "solana-sanitize", + "wincode", ] [[package]] @@ -1573,7 +3420,7 @@ checksum = "2585f70191623887329dfb5078da3a00e15e3980ea67f42c2e10b07028419f43" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 4.2.0", "solana-sdk-ids", "solana-sysvar-id", ] @@ -1615,86 +3462,313 @@ dependencies = [ "solana-instruction", "solana-program-error", "solana-pubkey 3.0.0", - "solana-system-interface", + "solana-system-interface 2.0.0", + "solana-sysvar", + "solana-sysvar-id", +] + +[[package]] +name = "solana-svm-callback" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c895f1add5c9ceff634f485554ddbcbceb88cba71b2f753c4caaba461690d2c6" +dependencies = [ + "solana-account", + "solana-clock", + "solana-precompile-error", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "solana-svm-feature-set" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5addc8fc7beb262aed2df0c34322a04a1b07b82d35fac0a34cd01f5263f7e971" + +[[package]] +name = "solana-svm-log-collector" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e985304ae8370c2b14c5c31c3e4dfdd18bc38ba806ee341655119430116c1f0" +dependencies = [ + "log", +] + +[[package]] +name = "solana-svm-measure" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bc239ef12213c45a4077799a154f340b290938973ad11dc4aaedee8fe39319" + +[[package]] +name = "solana-svm-timings" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7bc8099ec662531e751607c096a2b336502b592ddd2cf584ec8312fd499fa8" +dependencies = [ + "eager", + "enum-iterator", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "solana-svm-transaction" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29a9d25c729620fc70664e17d787a7804e52903da6fc94810e5dac7ca3217064" +dependencies = [ + "solana-hash 3.1.0", + "solana-message", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-signature", + "solana-transaction", +] + +[[package]] +name = "solana-svm-type-overrides" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5093201eaac4a41edcaab9fc0060712d5bce2d2a0ca6134d18e9bcac2b3739bc" +dependencies = [ + "rand 0.8.5", +] + +[[package]] +name = "solana-system-interface" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e1790547bfc3061f1ee68ea9d8dc6c973c02a163697b24263a8e9f2e6d4afa2" +dependencies = [ + "num-traits", + "serde", + "serde_derive", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "solana-system-interface" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a95a6f2e23ed861d6444ad4a6d6896c418d7d101b960787e65a8e33157cee81b" +dependencies = [ + "num-traits", + "serde", + "serde_derive", + "solana-address 2.5.0", + "solana-instruction", + "solana-msg", + "solana-program-error", +] + +[[package]] +name = "solana-system-program" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab198a979e1bfa90e5a481fd3cec77326660e182668a248020cbd427c0ea1b5f" +dependencies = [ + "bincode", + "log", + "serde", + "solana-account", + "solana-bincode", + "solana-fee-calculator", + "solana-instruction", + "solana-nonce", + "solana-nonce-account", + "solana-packet", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-svm-log-collector", + "solana-svm-type-overrides", + "solana-system-interface 2.0.0", "solana-sysvar", + "solana-transaction-context", +] + +[[package]] +name = "solana-sysvar" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6690d3dd88f15c21edff68eb391ef8800df7a1f5cec84ee3e8d1abf05affdf74" +dependencies = [ + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "lazy_static", + "serde", + "serde_derive", + "solana-account-info", + "solana-clock", + "solana-define-syscall 4.0.1", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-fee-calculator", + "solana-hash 4.2.0", + "solana-instruction", + "solana-last-restart-slot", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-pubkey 4.1.0", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-slot-hashes", + "solana-slot-history", "solana-sysvar-id", ] [[package]] -name = "solana-system-interface" -version = "2.0.0" +name = "solana-sysvar-id" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17358d1e9a13e5b9c2264d301102126cf11a47fd394cdf3dec174fe7bc96e1de" +dependencies = [ + "solana-address 2.5.0", + "solana-sdk-ids", +] + +[[package]] +name = "solana-transaction" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96697cff5075a028265324255efed226099f6d761ca67342b230d09f72cc48d2" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-address 2.5.0", + "solana-hash 4.2.0", + "solana-instruction", + "solana-instruction-error", + "solana-message", + "solana-sanitize", + "solana-sdk-ids", + "solana-short-vec", + "solana-signature", + "solana-signer", + "solana-transaction-error", +] + +[[package]] +name = "solana-transaction-context" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c4936df4b86a943ea6d552ca2c64fcc0d1a06dee2193cbf463eaedc372736d" +dependencies = [ + "bincode", + "serde", + "solana-account", + "solana-instruction", + "solana-instructions-sysvar", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sbpf", + "solana-sdk-ids", +] + +[[package]] +name = "solana-transaction-error" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8396904805b0b385b9de115a652fe80fd01e5b98ce0513f4fcd8184ada9bb792" +dependencies = [ + "serde", + "serde_derive", + "solana-instruction-error", + "solana-sanitize", +] + +[[package]] +name = "solana-vote-interface" +version = "4.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e1790547bfc3061f1ee68ea9d8dc6c973c02a163697b24263a8e9f2e6d4afa2" +checksum = "db6e123e16bfdd7a81d71b4c4699e0b29580b619f4cd2ef5b6aae1eb85e8979f" dependencies = [ + "bincode", + "cfg_eval", + "num-derive", "num-traits", "serde", "serde_derive", + "serde_with", + "solana-clock", + "solana-hash 3.1.0", "solana-instruction", - "solana-msg", - "solana-program-error", + "solana-instruction-error", "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-serde-varint", + "solana-serialize-utils", + "solana-short-vec", + "solana-system-interface 2.0.0", ] [[package]] -name = "solana-sysvar" -version = "3.1.1" +name = "solana-vote-program" +version = "3.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6690d3dd88f15c21edff68eb391ef8800df7a1f5cec84ee3e8d1abf05affdf74" +checksum = "55e2eab8557ff61ae2f58ebdb63aabf3579e04eb3dd07e8b4c4102704a137bae" dependencies = [ - "base64 0.22.1", + "agave-feature-set", "bincode", - "lazy_static", + "log", + "num-derive", + "num-traits", "serde", - "serde_derive", - "solana-account-info", + "solana-account", + "solana-bincode", "solana-clock", - "solana-define-syscall 4.0.1", - "solana-epoch-rewards", "solana-epoch-schedule", - "solana-fee-calculator", - "solana-hash", + "solana-hash 3.1.0", "solana-instruction", - "solana-last-restart-slot", - "solana-program-entrypoint", - "solana-program-error", - "solana-program-memory", - "solana-pubkey 4.1.0", - "solana-rent", + "solana-keypair", + "solana-packet", + "solana-program-runtime", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", "solana-sdk-ids", - "solana-sdk-macro", + "solana-signer", "solana-slot-hashes", - "solana-slot-history", - "solana-sysvar-id", -] - -[[package]] -name = "solana-sysvar-id" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17358d1e9a13e5b9c2264d301102126cf11a47fd394cdf3dec174fe7bc96e1de" -dependencies = [ - "solana-address 2.4.0", - "solana-sdk-ids", + "solana-transaction", + "solana-transaction-context", + "solana-vote-interface", + "thiserror 2.0.18", ] [[package]] -name = "solana-transaction-error" -version = "3.1.0" +name = "solana-zero-copy" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8396904805b0b385b9de115a652fe80fd01e5b98ce0513f4fcd8184ada9bb792" +checksum = "94f52dd8f733a13f6a18e55de83cf97c4c3f5fdf27ea3830bcff0b35313efcc2" dependencies = [ - "solana-instruction-error", - "solana-sanitize", + "borsh", + "bytemuck", + "bytemuck_derive", ] [[package]] -name = "solana-zero-copy" -version = "1.0.0" +name = "solana-zk-elgamal-proof-program" +version = "3.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f52dd8f733a13f6a18e55de83cf97c4c3f5fdf27ea3830bcff0b35313efcc2" +checksum = "98ebd77845de672972a32c357d7a68f2cc16c1037cc0ebf550ebba167827c10c" dependencies = [ + "agave-feature-set", "bytemuck", - "bytemuck_derive", + "num-derive", + "num-traits", + "solana-instruction", + "solana-program-runtime", + "solana-sdk-ids", + "solana-svm-log-collector", + "solana-zk-sdk", ] [[package]] @@ -1709,13 +3783,13 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek", - "getrandom", - "itertools", + "getrandom 0.2.17", + "itertools 0.12.1", "js-sys", "merlin", "num-derive", "num-traits", - "rand", + "rand 0.8.5", "serde", "serde_derive", "serde_json", @@ -1734,12 +3808,100 @@ dependencies = [ "zeroize", ] +[[package]] +name = "solana-zk-token-proof-program" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c13a05831857b4e3320d98cdd77a3f7b645566508d8f66a07c9168ac1e8bc68" +dependencies = [ + "agave-feature-set", + "bytemuck", + "num-derive", + "num-traits", + "solana-instruction", + "solana-program-runtime", + "solana-sdk-ids", + "solana-svm-log-collector", + "solana-zk-token-sdk", +] + +[[package]] +name = "solana-zk-token-sdk" +version = "3.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8dab3f2df045b7bec3cb3e1cff0889ec46d776191c3a2af19a77ddd3c4c6fc" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek", + "itertools 0.12.1", + "merlin", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_json", + "sha3", + "solana-curve25519", + "solana-derivation-path", + "solana-instruction", + "solana-pubkey 3.0.0", + "solana-sdk-ids", + "solana-seed-derivable", + "solana-seed-phrase", + "solana-signature", + "solana-signer", + "subtle", + "thiserror 2.0.18", + "zeroize", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "spl-associated-token-account" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0242277e290c023de8826f504abcf9206b3cd4e18d9ace4ec59a698b2828e88b" +dependencies = [ + "borsh", + "num-derive", + "num-traits", + "solana-account-info", + "solana-cpi", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-system-interface 2.0.0", + "solana-sysvar", + "spl-associated-token-account-interface", + "spl-token-2022-interface", + "spl-token-interface", + "thiserror 2.0.18", +] + [[package]] name = "spl-associated-token-account-interface" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6433917b60441d68d99a17e121d9db0ea15a9a69c0e5afa34649cf5ba12612f" dependencies = [ + "borsh", "solana-instruction", "solana-pubkey 3.0.0", ] @@ -1769,22 +3931,22 @@ dependencies = [ [[package]] name = "spl-discriminator-syn" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f05593b7ca9eac7caca309720f2eafb96355e037e6d373b909a80fe7b69b9" +checksum = "5d1dbc82ab91422345b6df40a79e2b78c7bce1ebb366da323572dd60b7076b67" dependencies = [ "proc-macro2", "quote", - "sha2", + "sha2 0.10.9", "syn 2.0.117", "thiserror 1.0.69", ] [[package]] name = "spl-pod" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f3df240f67bea453d4bc5749761e45436d14b9457ed667e0300555d5c271f3" +checksum = "2f9c6e142cdf1e7e77f480053ec9f0ce989890768ddf91f619b50f39d1b456f5" dependencies = [ "borsh", "bytemuck", @@ -1795,10 +3957,39 @@ dependencies = [ "solana-program-error", "solana-program-option", "solana-pubkey 3.0.0", + "solana-zero-copy", "solana-zk-sdk", "thiserror 2.0.18", ] +[[package]] +name = "spl-token" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878b0183d51fcd8a53e1604f4c13321894cf53227e6773c529b0d03d499a8dfd" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-account-info", + "solana-cpi", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-program-option", + "solana-program-pack", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids", + "solana-sysvar", + "spl-token-interface", + "thiserror 2.0.18", +] + [[package]] name = "spl-token-2022-interface" version = "2.1.0" @@ -1868,7 +4059,7 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-address 2.4.0", + "solana-address 2.5.0", "solana-instruction", "solana-nullable", "solana-program-error", @@ -2009,9 +4200,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -2024,85 +4215,92 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.14" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", - "toml_datetime 0.6.6", - "toml_edit 0.22.14", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_datetime" -version = "1.1.0+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", "serde_spanned", - "toml_datetime 0.6.6", - "winnow 0.6.13", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.25.8+spec-1.1.0" +version = "0.25.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16bff38f1d86c47f9ff0647e6838d7bb362522bdf44006c7068c2b1e606f1f3c" +checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" dependencies = [ "indexmap", - "toml_datetime 1.1.0+spec-1.1.0", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.0", + "winnow 1.0.1", ] [[package]] name = "toml_parser" -version = "1.1.0+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.0", + "winnow 1.0.1", ] +[[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.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "universal-hash" @@ -2110,10 +4308,19 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + [[package]] name = "uriparse" version = "0.6.4" @@ -2126,48 +4333,55 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] -name = "wasm-bindgen" -version = "0.2.104" +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" +name = "wasm-bindgen" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.117", + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2175,31 +4389,53 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn 2.0.117", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "wincode" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc91ddd8c932a38bbec58ed536d9e93ce9cd01b6af9b6de3c501132cf98ddec6" +checksum = "657690780ce23e6f66576a782ffd88eb353512381817029cc1d7a99154bb6d1f" dependencies = [ "pastey", "proc-macro2", @@ -2214,92 +4450,60 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fca057fc9a13dd19cdb64ef558635d43c42667c0afa1ae7915ea1fa66993fd1a" dependencies = [ - "darling", + "darling 0.21.3", "proc-macro2", "quote", "syn 2.0.117", ] [[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" +name = "winnow" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" +name = "winnow" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] -name = "winnow" -version = "0.6.13" +name = "zerocopy" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ - "memchr", + "zerocopy-derive", ] [[package]] -name = "winnow" -version = "1.0.0" +name = "zerocopy-derive" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ - "memchr", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -2313,11 +4517,17 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", "syn 2.0.117", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/tokens/token-fundraiser/anchor/package.json b/tokens/token-fundraiser/anchor/package.json index ec93e2a0e..78c8eba57 100644 --- a/tokens/token-fundraiser/anchor/package.json +++ b/tokens/token-fundraiser/anchor/package.json @@ -1,23 +1,23 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.4.6" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.4.6" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-fundraiser/anchor/pnpm-lock.yaml b/tokens/token-fundraiser/anchor/pnpm-lock.yaml index 541bb9af2..4ff72e6de 100644 --- a/tokens/token-fundraiser/anchor/pnpm-lock.yaml +++ b/tokens/token-fundraiser/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.4.6 version: 0.4.6(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -48,18 +48,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.28.4': @@ -854,16 +854,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -881,7 +881,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.28.4': {} diff --git a/tokens/token-fundraiser/anchor/programs/fundraiser/Cargo.toml b/tokens/token-fundraiser/anchor/programs/fundraiser/Cargo.toml index 092f60dcf..de7b3bf04 100644 --- a/tokens/token-fundraiser/anchor/programs/fundraiser/Cargo.toml +++ b/tokens/token-fundraiser/anchor/programs/fundraiser/Cargo.toml @@ -20,8 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = "1.0.0-rc.5" # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = "1.0.0" + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-fundraiser/anchor/programs/fundraiser/src/lib.rs b/tokens/token-fundraiser/anchor/programs/fundraiser/src/lib.rs index 12d34638f..8f171527a 100644 --- a/tokens/token-fundraiser/anchor/programs/fundraiser/src/lib.rs +++ b/tokens/token-fundraiser/anchor/programs/fundraiser/src/lib.rs @@ -1,6 +1,6 @@ use anchor_lang::prelude::*; -declare_id!("Eoiuq1dXvHxh6dLx3wh9gj8kSAUpga11krTrbfF5XYsC"); +declare_id!("EuqudshRf8VRskatC6U3txgivHmtCkY5d1qsK5B3VAio"); mod constants; mod error; diff --git a/tokens/token-fundraiser/anchor/programs/fundraiser/tests/test_fundraiser.rs b/tokens/token-fundraiser/anchor/programs/fundraiser/tests/test_fundraiser.rs new file mode 100644 index 000000000..c17869dee --- /dev/null +++ b/tokens/token-fundraiser/anchor/programs/fundraiser/tests/test_fundraiser.rs @@ -0,0 +1,424 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{ + create_associated_token_account, create_token_mint, create_wallet, + get_token_account_balance, mint_tokens_to_token_account, send_transaction_from_instructions, + }, + solana_signer::Signer, +}; + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn ata_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn derive_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey { + let (ata, _bump) = Pubkey::find_program_address( + &[wallet.as_ref(), token_program_id().as_ref(), mint.as_ref()], + &ata_program_id(), + ); + ata +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = fundraiser::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/fundraiser.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 100_000_000_000).unwrap(); + (svm, program_id, payer) +} + +struct FundraiserSetup { + svm: LiteSVM, + program_id: Pubkey, + payer: Keypair, + maker: Keypair, + mint: Pubkey, + fundraiser_pda: Pubkey, + vault: Pubkey, +} + +fn full_setup() -> FundraiserSetup { + let (mut svm, program_id, payer) = setup(); + + let maker = create_wallet(&mut svm, 10_000_000_000).unwrap(); + + // Create mint (6 decimals) — payer is mint authority + let mint = create_token_mint(&mut svm, &payer, 6, None).unwrap(); + + // Derive the fundraiser PDA + let (fundraiser_pda, _bump) = Pubkey::find_program_address( + &[b"fundraiser", maker.pubkey().as_ref()], + &program_id, + ); + + // Vault is the ATA of the fundraiser PDA for the mint + let vault = derive_ata(&fundraiser_pda, &mint); + + FundraiserSetup { + svm, + program_id, + payer, + maker, + mint, + fundraiser_pda, + vault, + } +} + +#[test] +fn test_initialize_fundraiser() { + let mut fs = full_setup(); + + let amount_to_raise: u64 = 30_000_000; + let duration: u16 = 0; + + let init_ix = Instruction::new_with_bytes( + fs.program_id, + &fundraiser::instruction::Initialize { + amount: amount_to_raise, + duration, + } + .data(), + fundraiser::accounts::Initialize { + maker: fs.maker.pubkey(), + mint_to_raise: fs.mint, + fundraiser: fs.fundraiser_pda, + vault: fs.vault, + system_program: system_program::id(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut fs.svm, + vec![init_ix], + &[&fs.maker], + &fs.maker.pubkey(), + ) + .unwrap(); + + // Verify fundraiser account exists + let fundraiser_data = fs + .svm + .get_account(&fs.fundraiser_pda) + .expect("Fundraiser account should exist"); + assert!(!fundraiser_data.data.is_empty()); + + // Verify vault exists with zero balance + assert_eq!(get_token_account_balance(&fs.svm, &fs.vault).unwrap(), 0); +} + +#[test] +fn test_contribute_and_refund() { + let mut fs = full_setup(); + + let amount_to_raise: u64 = 30_000_000; + let duration: u16 = 0; + + // Initialize fundraiser + let init_ix = Instruction::new_with_bytes( + fs.program_id, + &fundraiser::instruction::Initialize { + amount: amount_to_raise, + duration, + } + .data(), + fundraiser::accounts::Initialize { + maker: fs.maker.pubkey(), + mint_to_raise: fs.mint, + fundraiser: fs.fundraiser_pda, + vault: fs.vault, + system_program: system_program::id(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut fs.svm, + vec![init_ix], + &[&fs.maker], + &fs.maker.pubkey(), + ) + .unwrap(); + + // Setup contributor using Kite + let contributor = create_wallet(&mut fs.svm, 10_000_000_000).unwrap(); + + let contributor_ata = + create_associated_token_account(&mut fs.svm, &contributor.pubkey(), &fs.mint, &fs.payer) + .unwrap(); + + let mint_amount: u64 = 10_000_000; + mint_tokens_to_token_account(&mut fs.svm, &fs.mint, &contributor_ata, mint_amount, &fs.payer) + .unwrap(); + + // Derive contributor account PDA + let (contributor_account_pda, _bump) = Pubkey::find_program_address( + &[ + b"contributor", + fs.fundraiser_pda.as_ref(), + contributor.pubkey().as_ref(), + ], + &fs.program_id, + ); + + // Contribute 1_000_000 + let contribute_amount: u64 = 1_000_000; + let contribute_ix = Instruction::new_with_bytes( + fs.program_id, + &fundraiser::instruction::Contribute { + amount: contribute_amount, + } + .data(), + fundraiser::accounts::Contribute { + contributor: contributor.pubkey(), + mint_to_raise: fs.mint, + fundraiser: fs.fundraiser_pda, + contributor_account: contributor_account_pda, + contributor_ata, + vault: fs.vault, + token_program: token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut fs.svm, + vec![contribute_ix], + &[&contributor], + &contributor.pubkey(), + ) + .unwrap(); + + // Verify vault balance + assert_eq!( + get_token_account_balance(&fs.svm, &fs.vault).unwrap(), + contribute_amount + ); + + // Expire blockhash to avoid AlreadyProcessed error (same accounts, same amount = same tx hash) + fs.svm.expire_blockhash(); + + // Contribute again + let contribute_ix2 = Instruction::new_with_bytes( + fs.program_id, + &fundraiser::instruction::Contribute { + amount: contribute_amount, + } + .data(), + fundraiser::accounts::Contribute { + contributor: contributor.pubkey(), + mint_to_raise: fs.mint, + fundraiser: fs.fundraiser_pda, + contributor_account: contributor_account_pda, + contributor_ata, + vault: fs.vault, + token_program: token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut fs.svm, + vec![contribute_ix2], + &[&contributor], + &contributor.pubkey(), + ) + .unwrap(); + + // Verify vault balance is now 2_000_000 + assert_eq!( + get_token_account_balance(&fs.svm, &fs.vault).unwrap(), + contribute_amount * 2 + ); + + fs.svm.expire_blockhash(); + + // Refund + let refund_ix = Instruction::new_with_bytes( + fs.program_id, + &fundraiser::instruction::Refund {}.data(), + fundraiser::accounts::Refund { + contributor: contributor.pubkey(), + maker: fs.maker.pubkey(), + mint_to_raise: fs.mint, + fundraiser: fs.fundraiser_pda, + contributor_account: contributor_account_pda, + contributor_ata, + vault: fs.vault, + token_program: token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut fs.svm, + vec![refund_ix], + &[&contributor], + &contributor.pubkey(), + ) + .unwrap(); + + // Verify vault is empty after refund + assert_eq!(get_token_account_balance(&fs.svm, &fs.vault).unwrap(), 0); + + // Verify contributor got tokens back + assert_eq!( + get_token_account_balance(&fs.svm, &contributor_ata).unwrap(), + mint_amount + ); + + // Contributor account PDA should be closed + assert!( + fs.svm.get_account(&contributor_account_pda).is_none(), + "Contributor account should be closed after refund" + ); +} + +#[test] +fn test_check_contributions_success() { + let mut fs = full_setup(); + + let amount_to_raise: u64 = 1_000; + let duration: u16 = 0; + + // Initialize fundraiser + let init_ix = Instruction::new_with_bytes( + fs.program_id, + &fundraiser::instruction::Initialize { + amount: amount_to_raise, + duration, + } + .data(), + fundraiser::accounts::Initialize { + maker: fs.maker.pubkey(), + mint_to_raise: fs.mint, + fundraiser: fs.fundraiser_pda, + vault: fs.vault, + system_program: system_program::id(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut fs.svm, + vec![init_ix], + &[&fs.maker], + &fs.maker.pubkey(), + ) + .unwrap(); + + // Need 10 contributors each contributing 100 (10% of 1000) to reach goal + for _ in 0..10 { + let contributor = create_wallet(&mut fs.svm, 10_000_000_000).unwrap(); + + let contributor_ata = create_associated_token_account( + &mut fs.svm, + &contributor.pubkey(), + &fs.mint, + &fs.payer, + ) + .unwrap(); + + mint_tokens_to_token_account(&mut fs.svm, &fs.mint, &contributor_ata, 10_000, &fs.payer) + .unwrap(); + + let (contributor_pda, _) = Pubkey::find_program_address( + &[ + b"contributor", + fs.fundraiser_pda.as_ref(), + contributor.pubkey().as_ref(), + ], + &fs.program_id, + ); + + let contribute_ix = Instruction::new_with_bytes( + fs.program_id, + &fundraiser::instruction::Contribute { amount: 100 }.data(), + fundraiser::accounts::Contribute { + contributor: contributor.pubkey(), + mint_to_raise: fs.mint, + fundraiser: fs.fundraiser_pda, + contributor_account: contributor_pda, + contributor_ata, + vault: fs.vault, + token_program: token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut fs.svm, + vec![contribute_ix], + &[&contributor], + &contributor.pubkey(), + ) + .unwrap(); + + // Check if we've hit the goal + let current = get_token_account_balance(&fs.svm, &fs.vault).unwrap(); + if current >= amount_to_raise { + break; + } + } + + // Verify vault has enough + assert!(get_token_account_balance(&fs.svm, &fs.vault).unwrap() >= amount_to_raise); + + // Check contributions (maker claims the funds) + let maker_ata = derive_ata(&fs.maker.pubkey(), &fs.mint); + + let check_ix = Instruction::new_with_bytes( + fs.program_id, + &fundraiser::instruction::CheckContributions {}.data(), + fundraiser::accounts::CheckContributions { + maker: fs.maker.pubkey(), + mint_to_raise: fs.mint, + fundraiser: fs.fundraiser_pda, + vault: fs.vault, + maker_ata, + token_program: token_program_id(), + system_program: system_program::id(), + associated_token_program: ata_program_id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut fs.svm, + vec![check_ix], + &[&fs.maker], + &fs.maker.pubkey(), + ) + .unwrap(); + + // Verify maker received the funds + assert!( + get_token_account_balance(&fs.svm, &maker_ata).unwrap() >= amount_to_raise + ); + + // Fundraiser account should be closed + assert!( + fs.svm.get_account(&fs.fundraiser_pda).is_none(), + "Fundraiser account should be closed after check_contributions" + ); +} diff --git a/tokens/token-fundraiser/anchor/tests/bankrun.test.ts b/tokens/token-fundraiser/anchor/tests/bankrun.test.ts index 86baeb62d..ce11539aa 100644 --- a/tokens/token-fundraiser/anchor/tests/bankrun.test.ts +++ b/tokens/token-fundraiser/anchor/tests/bankrun.test.ts @@ -2,27 +2,23 @@ import { describe, it } from "node:test"; import * as anchor from "@anchor-lang/core"; import { ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, createMint, getAssociatedTokenAddressSync, getOrCreateAssociatedTokenAccount, mintTo, + TOKEN_PROGRAM_ID, } from "@solana/spl-token"; import { PublicKey } from "@solana/web3.js"; import { BankrunProvider } from "anchor-bankrun"; import BN from "bn.js"; import { startAnchor } from "solana-bankrun"; +import IDL from "../target/idl/fundraiser.json"; import type { Fundraiser } from "../target/types/fundraiser"; -import IDL from "../target/idl/fundraiser.json"; const PROGRAM_ID = new PublicKey(IDL.address); describe("fundraiser bankrun", async () => { - const context = await startAnchor( - "", - [{ name: "fundraiser", programId: PROGRAM_ID }], - [] - ); + const context = await startAnchor("", [{ name: "fundraiser", programId: PROGRAM_ID }], []); const provider = new BankrunProvider(context); anchor.setProvider(provider); const wallet = provider.wallet as anchor.Wallet; @@ -38,16 +34,12 @@ describe("fundraiser bankrun", async () => { const fundraiser = anchor.web3.PublicKey.findProgramAddressSync( [Buffer.from("fundraiser"), maker.publicKey.toBuffer()], - program.programId + program.programId, )[0]; const contributor = anchor.web3.PublicKey.findProgramAddressSync( - [ - Buffer.from("contributor"), - fundraiser.toBuffer(), - provider.publicKey.toBuffer(), - ], - program.programId + [Buffer.from("contributor"), fundraiser.toBuffer(), provider.publicKey.toBuffer()], + program.programId, )[0]; const confirm = async (signature: string): Promise => { @@ -65,32 +57,15 @@ describe("fundraiser bankrun", async () => { .then(confirm); console.log("\nAirdropped 1 SOL to maker", airdrop); - mint = await createMint( - provider.connection, - wallet.payer, - provider.publicKey, - provider.publicKey, - 6 - ); + mint = await createMint(provider.connection, wallet.payer, provider.publicKey, provider.publicKey, 6); console.log("Mint created", mint.toBase58()); contributorATA = ( - await getOrCreateAssociatedTokenAccount( - provider.connection, - wallet.payer, - mint, - wallet.publicKey - ) + await getOrCreateAssociatedTokenAccount(provider.connection, wallet.payer, mint, wallet.publicKey) ).address; - makerATA = ( - await getOrCreateAssociatedTokenAccount( - provider.connection, - wallet.payer, - mint, - maker.publicKey - ) - ).address; + makerATA = (await getOrCreateAssociatedTokenAccount(provider.connection, wallet.payer, mint, maker.publicKey)) + .address; const mintTx = await mintTo( provider.connection, @@ -98,7 +73,7 @@ describe("fundraiser bankrun", async () => { mint, contributorATA, provider.publicKey, - 1_000_000_0 + 1_000_000_0, ); console.log("Minted 10 tokens to contributor", mintTx); }); @@ -143,14 +118,9 @@ describe("fundraiser bankrun", async () => { console.log("\nContributed to fundraiser", tx); console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount - ); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); - const contributorAccount = await program.account.contributor.fetch( - contributor - ); + const contributorAccount = await program.account.contributor.fetch(contributor); console.log("Contributor balance", contributorAccount.amount.toString()); }); it("Contribute to Fundraiser", async () => { @@ -171,14 +141,9 @@ describe("fundraiser bankrun", async () => { console.log("\nContributed to fundraiser", tx); console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount - ); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); - const contributorAccount = await program.account.contributor.fetch( - contributor - ); + const contributorAccount = await program.account.contributor.fetch(contributor); console.log("Contributor balance", contributorAccount.amount.toString()); }); @@ -201,10 +166,7 @@ describe("fundraiser bankrun", async () => { console.log("\nContributed to fundraiser", tx); console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount - ); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); } catch (error) { console.log("\nError contributing to fundraiser"); console.log(error.msg); @@ -231,10 +193,7 @@ describe("fundraiser bankrun", async () => { console.log("\nChecked contributions"); console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount - ); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); } catch (error) { console.log("\nError checking contributions"); console.log(error.msg); @@ -244,9 +203,7 @@ describe("fundraiser bankrun", async () => { it("Refund Contributions", async () => { const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); - const contributorAccount = await program.account.contributor.fetch( - contributor - ); + const contributorAccount = await program.account.contributor.fetch(contributor); console.log("\nContributor balance", contributorAccount.amount.toString()); const tx = await program.methods @@ -267,9 +224,6 @@ describe("fundraiser bankrun", async () => { console.log("\nRefunded contributions", tx); console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount - ); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); }); }); diff --git a/tokens/token-fundraiser/anchor/tests/fundraiser.ts b/tokens/token-fundraiser/anchor/tests/fundraiser.ts index 5f86d630f..8077df4f1 100644 --- a/tokens/token-fundraiser/anchor/tests/fundraiser.ts +++ b/tokens/token-fundraiser/anchor/tests/fundraiser.ts @@ -2,264 +2,225 @@ import type { Program } from "@anchor-lang/core"; import * as anchor from "@anchor-lang/core"; import type NodeWallet from "@anchor-lang/core/dist/cjs/nodewallet"; import { - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - createMint, - getAssociatedTokenAddressSync, - getOrCreateAssociatedTokenAccount, - mintTo, + ASSOCIATED_TOKEN_PROGRAM_ID, + createMint, + getAssociatedTokenAddressSync, + getOrCreateAssociatedTokenAccount, + mintTo, + TOKEN_PROGRAM_ID, } from "@solana/spl-token"; import BN from "bn.js"; import type { Fundraiser } from "../target/types/fundraiser"; describe("fundraiser", () => { - // Configure the client to use the local cluster. - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - - const program = anchor.workspace.Fundraiser as Program; - - const maker = anchor.web3.Keypair.generate(); - - let mint: anchor.web3.PublicKey; - - let contributorATA: anchor.web3.PublicKey; - - let makerATA: anchor.web3.PublicKey; - - const wallet = provider.wallet as NodeWallet; - - const fundraiser = anchor.web3.PublicKey.findProgramAddressSync( - [Buffer.from("fundraiser"), maker.publicKey.toBuffer()], - program.programId, - )[0]; - - const contributor = anchor.web3.PublicKey.findProgramAddressSync( - [ - Buffer.from("contributor"), - fundraiser.toBuffer(), - provider.publicKey.toBuffer(), - ], - program.programId, - )[0]; - - const confirm = async (signature: string): Promise => { - const block = await provider.connection.getLatestBlockhash(); - await provider.connection.confirmTransaction({ - signature, - ...block, - }); - return signature; - }; - - it("Test Preparation", async () => { - const airdrop = await provider.connection - .requestAirdrop(maker.publicKey, 1 * anchor.web3.LAMPORTS_PER_SOL) - .then(confirm); - console.log("\nAirdropped 1 SOL to maker", airdrop); - - mint = await createMint( - provider.connection, - wallet.payer, - provider.publicKey, - provider.publicKey, - 6, - ); - console.log("Mint created", mint.toBase58()); - - contributorATA = ( - await getOrCreateAssociatedTokenAccount( - provider.connection, - wallet.payer, - mint, - wallet.publicKey, - ) - ).address; - - makerATA = ( - await getOrCreateAssociatedTokenAccount( - provider.connection, - wallet.payer, - mint, - maker.publicKey, - ) - ).address; - - const mintTx = await mintTo( - provider.connection, - wallet.payer, - mint, - contributorATA, - provider.publicKey, - 1_000_000_0, - ); - console.log("Minted 10 tokens to contributor", mintTx); - }); - - it("Initialize Fundaraiser", async () => { - const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); - - const tx = await program.methods - .initialize(new BN(30000000), 0) - .accountsPartial({ - maker: maker.publicKey, - fundraiser, - mintToRaise: mint, - vault, - systemProgram: anchor.web3.SystemProgram.programId, - tokenProgram: TOKEN_PROGRAM_ID, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - }) - .signers([maker]) - .rpc() - .then(confirm); - - console.log("\nInitialized fundraiser Account"); - console.log("Your transaction signature", tx); - }); - - it("Contribute to Fundraiser", async () => { - const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); - - const tx = await program.methods - .contribute(new BN(1000000)) - .accountsPartial({ - contributor: provider.publicKey, - fundraiser, - contributorAccount: contributor, - contributorAta: contributorATA, - vault, - tokenProgram: TOKEN_PROGRAM_ID, - }) - .rpc() - .then(confirm); - - console.log("\nContributed to fundraiser", tx); - console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount, - ); - - const contributorAccount = - await program.account.contributor.fetch(contributor); - console.log("Contributor balance", contributorAccount.amount.toString()); - }); - it("Contribute to Fundraiser", async () => { - const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); - - const tx = await program.methods - .contribute(new BN(1000000)) - .accountsPartial({ - contributor: provider.publicKey, - fundraiser, - contributorAccount: contributor, - contributorAta: contributorATA, - vault, - tokenProgram: TOKEN_PROGRAM_ID, - }) - .rpc() - .then(confirm); - - console.log("\nContributed to fundraiser", tx); - console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount, - ); - - const contributorAccount = - await program.account.contributor.fetch(contributor); - console.log("Contributor balance", contributorAccount.amount.toString()); - }); - - it("Contribute to Fundraiser - Robustness Test", async () => { - try { - const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); - - const tx = await program.methods - .contribute(new BN(2000000)) - .accountsPartial({ - contributor: provider.publicKey, - fundraiser, - contributorAccount: contributor, - contributorAta: contributorATA, - vault, - tokenProgram: TOKEN_PROGRAM_ID, - }) - .rpc() - .then(confirm); - - console.log("\nContributed to fundraiser", tx); - console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount, - ); - } catch (error) { - console.log("\nError contributing to fundraiser"); - console.log(error.msg); - } - }); - - it("Check contributions - Robustness Test", async () => { - try { - const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); - - const tx = await program.methods - .checkContributions() - .accountsPartial({ - maker: maker.publicKey, - mintToRaise: mint, - fundraiser, - makerAta: makerATA, - vault, - tokenProgram: TOKEN_PROGRAM_ID, - }) - .signers([maker]) - .rpc() - .then(confirm); - - console.log("\nChecked contributions"); - console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount, - ); - } catch (error) { - console.log("\nError checking contributions"); - console.log(error.msg); - } - }); - - it("Refund Contributions", async () => { - const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); - - const contributorAccount = - await program.account.contributor.fetch(contributor); - console.log("\nContributor balance", contributorAccount.amount.toString()); - - const tx = await program.methods - .refund() - .accountsPartial({ - contributor: provider.publicKey, - maker: maker.publicKey, - mintToRaise: mint, - fundraiser, - contributorAccount: contributor, - contributorAta: contributorATA, - vault, - tokenProgram: TOKEN_PROGRAM_ID, - systemProgram: anchor.web3.SystemProgram.programId, - }) - .rpc() - .then(confirm); - - console.log("\nRefunded contributions", tx); - console.log("Your transaction signature", tx); - console.log( - "Vault balance", - (await provider.connection.getTokenAccountBalance(vault)).value.amount, - ); - }); + // Configure the client to use the local cluster. + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + + const program = anchor.workspace.Fundraiser as Program; + + const maker = anchor.web3.Keypair.generate(); + + let mint: anchor.web3.PublicKey; + + let contributorATA: anchor.web3.PublicKey; + + let makerATA: anchor.web3.PublicKey; + + const wallet = provider.wallet as NodeWallet; + + const fundraiser = anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("fundraiser"), maker.publicKey.toBuffer()], + program.programId, + )[0]; + + const contributor = anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("contributor"), fundraiser.toBuffer(), provider.publicKey.toBuffer()], + program.programId, + )[0]; + + const confirm = async (signature: string): Promise => { + const block = await provider.connection.getLatestBlockhash(); + await provider.connection.confirmTransaction({ + signature, + ...block, + }); + return signature; + }; + + it("Test Preparation", async () => { + const airdrop = await provider.connection + .requestAirdrop(maker.publicKey, 1 * anchor.web3.LAMPORTS_PER_SOL) + .then(confirm); + console.log("\nAirdropped 1 SOL to maker", airdrop); + + mint = await createMint(provider.connection, wallet.payer, provider.publicKey, provider.publicKey, 6); + console.log("Mint created", mint.toBase58()); + + contributorATA = ( + await getOrCreateAssociatedTokenAccount(provider.connection, wallet.payer, mint, wallet.publicKey) + ).address; + + makerATA = (await getOrCreateAssociatedTokenAccount(provider.connection, wallet.payer, mint, maker.publicKey)) + .address; + + const mintTx = await mintTo( + provider.connection, + wallet.payer, + mint, + contributorATA, + provider.publicKey, + 1_000_000_0, + ); + console.log("Minted 10 tokens to contributor", mintTx); + }); + + it("Initialize Fundaraiser", async () => { + const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); + + const tx = await program.methods + .initialize(new BN(30000000), 0) + .accountsPartial({ + maker: maker.publicKey, + fundraiser, + mintToRaise: mint, + vault, + systemProgram: anchor.web3.SystemProgram.programId, + tokenProgram: TOKEN_PROGRAM_ID, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([maker]) + .rpc() + .then(confirm); + + console.log("\nInitialized fundraiser Account"); + console.log("Your transaction signature", tx); + }); + + it("Contribute to Fundraiser", async () => { + const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); + + const tx = await program.methods + .contribute(new BN(1000000)) + .accountsPartial({ + contributor: provider.publicKey, + fundraiser, + contributorAccount: contributor, + contributorAta: contributorATA, + vault, + tokenProgram: TOKEN_PROGRAM_ID, + }) + .rpc() + .then(confirm); + + console.log("\nContributed to fundraiser", tx); + console.log("Your transaction signature", tx); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); + + const contributorAccount = await program.account.contributor.fetch(contributor); + console.log("Contributor balance", contributorAccount.amount.toString()); + }); + it("Contribute to Fundraiser", async () => { + const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); + + const tx = await program.methods + .contribute(new BN(1000000)) + .accountsPartial({ + contributor: provider.publicKey, + fundraiser, + contributorAccount: contributor, + contributorAta: contributorATA, + vault, + tokenProgram: TOKEN_PROGRAM_ID, + }) + .rpc() + .then(confirm); + + console.log("\nContributed to fundraiser", tx); + console.log("Your transaction signature", tx); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); + + const contributorAccount = await program.account.contributor.fetch(contributor); + console.log("Contributor balance", contributorAccount.amount.toString()); + }); + + it("Contribute to Fundraiser - Robustness Test", async () => { + try { + const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); + + const tx = await program.methods + .contribute(new BN(2000000)) + .accountsPartial({ + contributor: provider.publicKey, + fundraiser, + contributorAccount: contributor, + contributorAta: contributorATA, + vault, + tokenProgram: TOKEN_PROGRAM_ID, + }) + .rpc() + .then(confirm); + + console.log("\nContributed to fundraiser", tx); + console.log("Your transaction signature", tx); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); + } catch (error) { + console.log("\nError contributing to fundraiser"); + console.log(error.msg); + } + }); + + it("Check contributions - Robustness Test", async () => { + try { + const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); + + const tx = await program.methods + .checkContributions() + .accountsPartial({ + maker: maker.publicKey, + mintToRaise: mint, + fundraiser, + makerAta: makerATA, + vault, + tokenProgram: TOKEN_PROGRAM_ID, + }) + .signers([maker]) + .rpc() + .then(confirm); + + console.log("\nChecked contributions"); + console.log("Your transaction signature", tx); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); + } catch (error) { + console.log("\nError checking contributions"); + console.log(error.msg); + } + }); + + it("Refund Contributions", async () => { + const vault = getAssociatedTokenAddressSync(mint, fundraiser, true); + + const contributorAccount = await program.account.contributor.fetch(contributor); + console.log("\nContributor balance", contributorAccount.amount.toString()); + + const tx = await program.methods + .refund() + .accountsPartial({ + contributor: provider.publicKey, + maker: maker.publicKey, + mintToRaise: mint, + fundraiser, + contributorAccount: contributor, + contributorAta: contributorATA, + vault, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: anchor.web3.SystemProgram.programId, + }) + .rpc() + .then(confirm); + + console.log("\nRefunded contributions", tx); + console.log("Your transaction signature", tx); + console.log("Vault balance", (await provider.connection.getTokenAccountBalance(vault)).value.amount); + }); }); diff --git a/tokens/token-swap/anchor/Anchor.toml b/tokens/token-swap/anchor/Anchor.toml index e119b88d6..f59559c68 100644 --- a/tokens/token-swap/anchor/Anchor.toml +++ b/tokens/token-swap/anchor/Anchor.toml @@ -15,7 +15,8 @@ cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +# LiteSVM Rust tests — replaced TS tests +test = "cargo test" [test] startup_wait = 5000 diff --git a/tokens/token-swap/anchor/package.json b/tokens/token-swap/anchor/package.json index 088bde1fe..6e7afcc30 100644 --- a/tokens/token-swap/anchor/package.json +++ b/tokens/token-swap/anchor/package.json @@ -1,21 +1,21 @@ { - "type": "module", - "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" - }, - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.3.8" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "prettier": "^2.6.2", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3" - } + "type": "module", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.3.8" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3" + } } diff --git a/tokens/token-swap/anchor/pnpm-lock.yaml b/tokens/token-swap/anchor/pnpm-lock.yaml index a753a5aeb..2f3913ca5 100644 --- a/tokens/token-swap/anchor/pnpm-lock.yaml +++ b/tokens/token-swap/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.3.8 version: 0.3.11(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -42,18 +42,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -854,16 +854,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.8)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 @@ -881,7 +881,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/token-swap/anchor/programs/token-swap/Cargo.toml b/tokens/token-swap/anchor/programs/token-swap/Cargo.toml index 5df2b828c..caa9e13f6 100644 --- a/tokens/token-swap/anchor/programs/token-swap/Cargo.toml +++ b/tokens/token-swap/anchor/programs/token-swap/Cargo.toml @@ -20,9 +20,16 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = { version = "1.0.0-rc.5", features = ["metadata"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = { version = "1.0.0", features = ["metadata"] } fixed = "1.27.0" +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/token-swap/anchor/programs/token-swap/src/lib.rs b/tokens/token-swap/anchor/programs/token-swap/src/lib.rs index d14e89724..333b7eba2 100644 --- a/tokens/token-swap/anchor/programs/token-swap/src/lib.rs +++ b/tokens/token-swap/anchor/programs/token-swap/src/lib.rs @@ -6,7 +6,7 @@ mod instructions; mod state; // Set the correct key here -declare_id!("AsGVFxWqEn8icRBFQApxJe68x3r9zvfSbmiEzYFATGYn"); +declare_id!("9FX4TuhmPbKEavcP431ALEzrvsrEaUNogPYcMZL37CeS"); #[program] pub mod swap_example { diff --git a/tokens/token-swap/anchor/programs/token-swap/tests/test_swap.rs b/tokens/token-swap/anchor/programs/token-swap/tests/test_swap.rs new file mode 100644 index 000000000..a8bcb6eba --- /dev/null +++ b/tokens/token-swap/anchor/programs/token-swap/tests/test_swap.rs @@ -0,0 +1,437 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{ + create_associated_token_account, create_token_mint, create_wallet, + get_token_account_balance, mint_tokens_to_token_account, send_transaction_from_instructions, + }, + solana_signer::Signer, +}; + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn ata_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn derive_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey { + let (ata, _bump) = Pubkey::find_program_address( + &[wallet.as_ref(), token_program_id().as_ref(), mint.as_ref()], + &ata_program_id(), + ); + ata +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = swap_example::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/swap_example.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let payer = create_wallet(&mut svm, 100_000_000_000).unwrap(); + (svm, program_id, payer) +} + +/// Ensure mint_a < mint_b by pubkey ordering (the program may require this). +fn ordered_mints(svm: &mut LiteSVM, authority: &Keypair, decimals: u8) -> (Pubkey, Pubkey) { + loop { + let a = create_token_mint(svm, authority, decimals, None).unwrap(); + let b = create_token_mint(svm, authority, decimals, None).unwrap(); + if a.as_ref() < b.as_ref() { + return (a, b); + } + } +} + +struct TestSetup { + svm: LiteSVM, + program_id: Pubkey, + payer: Keypair, + admin: Keypair, + amm_key: Pubkey, + mint_a: Pubkey, + mint_b: Pubkey, + pool_key: Pubkey, + pool_authority: Pubkey, + mint_liquidity: Pubkey, + pool_account_a: Pubkey, + pool_account_b: Pubkey, + holder_account_a: Pubkey, + holder_account_b: Pubkey, + liquidity_account: Pubkey, +} + +fn full_setup() -> TestSetup { + let (mut svm, program_id, payer) = setup(); + let admin = create_wallet(&mut svm, 100_000_000_000).unwrap(); + + let decimals: u8 = 6; + let minted_amount: u64 = 100 * 10u64.pow(decimals as u32); + + let (mint_a, mint_b) = ordered_mints(&mut svm, &admin, decimals); + let amm_id = Keypair::new().pubkey(); + let fee: u16 = 500; + + // Derive PDAs + let (amm_key, _) = Pubkey::find_program_address(&[amm_id.as_ref()], &program_id); + let (pool_key, _) = Pubkey::find_program_address( + &[amm_key.as_ref(), mint_a.as_ref(), mint_b.as_ref()], + &program_id, + ); + let (pool_authority, _) = Pubkey::find_program_address( + &[ + amm_key.as_ref(), + mint_a.as_ref(), + mint_b.as_ref(), + b"authority", + ], + &program_id, + ); + let (mint_liquidity, _) = Pubkey::find_program_address( + &[ + amm_key.as_ref(), + mint_a.as_ref(), + mint_b.as_ref(), + b"liquidity", + ], + &program_id, + ); + + let pool_account_a = derive_ata(&pool_authority, &mint_a); + let pool_account_b = derive_ata(&pool_authority, &mint_b); + let liquidity_account = derive_ata(&admin.pubkey(), &mint_liquidity); + + // Create ATAs for admin and mint tokens + let holder_account_a = + create_associated_token_account(&mut svm, &admin.pubkey(), &mint_a, &payer).unwrap(); + let holder_account_b = + create_associated_token_account(&mut svm, &admin.pubkey(), &mint_b, &payer).unwrap(); + + mint_tokens_to_token_account(&mut svm, &mint_a, &holder_account_a, minted_amount, &admin).unwrap(); + mint_tokens_to_token_account(&mut svm, &mint_b, &holder_account_b, minted_amount, &admin).unwrap(); + + // Create AMM + let create_amm_ix = Instruction::new_with_bytes( + program_id, + &swap_example::instruction::CreateAmm { id: amm_id, fee }.data(), + swap_example::accounts::CreateAmm { + amm: amm_key, + admin: admin.pubkey(), + payer: payer.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![create_amm_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); + + // Create Pool + let create_pool_ix = Instruction::new_with_bytes( + program_id, + &swap_example::instruction::CreatePool {}.data(), + swap_example::accounts::CreatePool { + amm: amm_key, + pool: pool_key, + pool_authority, + mint_liquidity, + mint_a, + mint_b, + pool_account_a, + pool_account_b, + payer: payer.pubkey(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![create_pool_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); + + TestSetup { + svm, + program_id, + payer, + admin, + amm_key, + mint_a, + mint_b, + pool_key, + pool_authority, + mint_liquidity, + pool_account_a, + pool_account_b, + holder_account_a, + holder_account_b, + liquidity_account, + } +} + +#[test] +fn test_create_amm() { + let (mut svm, program_id, payer) = setup(); + let amm_id = Keypair::new().pubkey(); + let fee: u16 = 500; + let admin = Keypair::new(); + + let (amm_key, _) = Pubkey::find_program_address(&[amm_id.as_ref()], &program_id); + + let create_amm_ix = Instruction::new_with_bytes( + program_id, + &swap_example::instruction::CreateAmm { id: amm_id, fee }.data(), + swap_example::accounts::CreateAmm { + amm: amm_key, + admin: admin.pubkey(), + payer: payer.pubkey(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut svm, + vec![create_amm_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); + + // Verify AMM account exists + let amm_account = svm.get_account(&amm_key).expect("AMM account should exist"); + assert!(!amm_account.data.is_empty()); +} + +#[test] +fn test_deposit_liquidity() { + let mut ts = full_setup(); + let deposit_amount_a: u64 = 4_000_000; + let deposit_amount_b: u64 = 1_000_000; + + let deposit_ix = Instruction::new_with_bytes( + ts.program_id, + &swap_example::instruction::DepositLiquidity { + amount_a: deposit_amount_a, + amount_b: deposit_amount_b, + } + .data(), + swap_example::accounts::DepositLiquidity { + pool: ts.pool_key, + pool_authority: ts.pool_authority, + depositor: ts.admin.pubkey(), + mint_liquidity: ts.mint_liquidity, + mint_a: ts.mint_a, + mint_b: ts.mint_b, + pool_account_a: ts.pool_account_a, + pool_account_b: ts.pool_account_b, + depositor_account_liquidity: ts.liquidity_account, + depositor_account_a: ts.holder_account_a, + depositor_account_b: ts.holder_account_b, + payer: ts.payer.pubkey(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + + send_transaction_from_instructions( + &mut ts.svm, + vec![deposit_ix], + &[&ts.payer, &ts.admin], + &ts.payer.pubkey(), + ) + .unwrap(); + + // Verify liquidity tokens were minted + let liq_amount = get_token_account_balance(&ts.svm, &ts.liquidity_account).unwrap(); + assert!(liq_amount > 0, "Should have received liquidity tokens"); +} + +#[test] +fn test_swap_a_to_b() { + let mut ts = full_setup(); + + // Deposit liquidity first + let deposit_ix = Instruction::new_with_bytes( + ts.program_id, + &swap_example::instruction::DepositLiquidity { + amount_a: 4_000_000, + amount_b: 1_000_000, + } + .data(), + swap_example::accounts::DepositLiquidity { + pool: ts.pool_key, + pool_authority: ts.pool_authority, + depositor: ts.admin.pubkey(), + mint_liquidity: ts.mint_liquidity, + mint_a: ts.mint_a, + mint_b: ts.mint_b, + pool_account_a: ts.pool_account_a, + pool_account_b: ts.pool_account_b, + depositor_account_liquidity: ts.liquidity_account, + depositor_account_a: ts.holder_account_a, + depositor_account_b: ts.holder_account_b, + payer: ts.payer.pubkey(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut ts.svm, + vec![deposit_ix], + &[&ts.payer, &ts.admin], + &ts.payer.pubkey(), + ) + .unwrap(); + + // Get balances before swap + let before_b = get_token_account_balance(&ts.svm, &ts.holder_account_b).unwrap(); + + // Swap 1M of token A for token B + let swap_ix = Instruction::new_with_bytes( + ts.program_id, + &swap_example::instruction::SwapExactTokensForTokens { + swap_a: true, + input_amount: 1_000_000, + min_output_amount: 100, + } + .data(), + swap_example::accounts::SwapExactTokensForTokens { + amm: ts.amm_key, + pool: ts.pool_key, + pool_authority: ts.pool_authority, + trader: ts.admin.pubkey(), + mint_a: ts.mint_a, + mint_b: ts.mint_b, + pool_account_a: ts.pool_account_a, + pool_account_b: ts.pool_account_b, + trader_account_a: ts.holder_account_a, + trader_account_b: ts.holder_account_b, + payer: ts.payer.pubkey(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut ts.svm, + vec![swap_ix], + &[&ts.payer, &ts.admin], + &ts.payer.pubkey(), + ) + .unwrap(); + + // After swap, token B balance should have increased + let after_b = get_token_account_balance(&ts.svm, &ts.holder_account_b).unwrap(); + assert!( + after_b > before_b, + "Token B balance should increase after swap A->B" + ); +} + +#[test] +fn test_withdraw_liquidity() { + let mut ts = full_setup(); + + // Deposit liquidity + let deposit_ix = Instruction::new_with_bytes( + ts.program_id, + &swap_example::instruction::DepositLiquidity { + amount_a: 4_000_000, + amount_b: 4_000_000, + } + .data(), + swap_example::accounts::DepositLiquidity { + pool: ts.pool_key, + pool_authority: ts.pool_authority, + depositor: ts.admin.pubkey(), + mint_liquidity: ts.mint_liquidity, + mint_a: ts.mint_a, + mint_b: ts.mint_b, + pool_account_a: ts.pool_account_a, + pool_account_b: ts.pool_account_b, + depositor_account_liquidity: ts.liquidity_account, + depositor_account_a: ts.holder_account_a, + depositor_account_b: ts.holder_account_b, + payer: ts.payer.pubkey(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut ts.svm, + vec![deposit_ix], + &[&ts.payer, &ts.admin], + &ts.payer.pubkey(), + ) + .unwrap(); + + // Get liquidity token balance + let liq_amount = get_token_account_balance(&ts.svm, &ts.liquidity_account).unwrap(); + assert!(liq_amount > 0); + + // Withdraw all liquidity + let withdraw_ix = Instruction::new_with_bytes( + ts.program_id, + &swap_example::instruction::WithdrawLiquidity { + amount: liq_amount, + } + .data(), + swap_example::accounts::WithdrawLiquidity { + amm: ts.amm_key, + pool: ts.pool_key, + pool_authority: ts.pool_authority, + depositor: ts.admin.pubkey(), + mint_liquidity: ts.mint_liquidity, + mint_a: ts.mint_a, + mint_b: ts.mint_b, + pool_account_a: ts.pool_account_a, + pool_account_b: ts.pool_account_b, + depositor_account_liquidity: ts.liquidity_account, + depositor_account_a: ts.holder_account_a, + depositor_account_b: ts.holder_account_b, + payer: ts.payer.pubkey(), + token_program: token_program_id(), + associated_token_program: ata_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut ts.svm, + vec![withdraw_ix], + &[&ts.payer, &ts.admin], + &ts.payer.pubkey(), + ) + .unwrap(); + + // Liquidity balance should be 0 + let liq_amount = get_token_account_balance(&ts.svm, &ts.liquidity_account).unwrap(); + assert_eq!(liq_amount, 0, "Liquidity should be fully withdrawn"); +} diff --git a/tokens/token-swap/anchor/tests/create-amm.ts b/tokens/token-swap/anchor/tests/create-amm.ts index 7eee680c4..081ac8b84 100644 --- a/tokens/token-swap/anchor/tests/create-amm.ts +++ b/tokens/token-swap/anchor/tests/create-amm.ts @@ -1,10 +1,10 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { expect } from 'chai'; -import type { SwapExample } from '../target/types/swap_example'; -import { createValues, expectRevert, type TestValues } from './utils'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { expect } from "chai"; +import type { SwapExample } from "../target/types/swap_example"; +import { createValues, expectRevert, type TestValues } from "./utils"; -describe('Create AMM', () => { +describe("Create AMM", () => { const provider = anchor.AnchorProvider.env(); const _connection = provider.connection; anchor.setProvider(provider); @@ -17,8 +17,11 @@ describe('Create AMM', () => { values = createValues(); }); - it('Creation', async () => { - await program.methods.createAmm(values.id, values.fee).accounts({ amm: values.ammKey, admin: values.admin.publicKey }).rpc(); + it("Creation", async () => { + await program.methods + .createAmm(values.id, values.fee) + .accounts({ amm: values.ammKey, admin: values.admin.publicKey }) + .rpc(); const ammAccount = await program.account.amm.fetch(values.ammKey); expect(ammAccount.id.toString()).to.equal(values.id.toString()); @@ -26,9 +29,14 @@ describe('Create AMM', () => { expect(ammAccount.fee.toString()).to.equal(values.fee.toString()); }); - it('Invalid fee', async () => { + it("Invalid fee", async () => { values.fee = 10000; - await expectRevert(program.methods.createAmm(values.id, values.fee).accounts({ amm: values.ammKey, admin: values.admin.publicKey }).rpc()); + await expectRevert( + program.methods + .createAmm(values.id, values.fee) + .accounts({ amm: values.ammKey, admin: values.admin.publicKey }) + .rpc(), + ); }); }); diff --git a/tokens/token-swap/anchor/tests/create-pool.ts b/tokens/token-swap/anchor/tests/create-pool.ts index cdab62af2..a8ff19609 100644 --- a/tokens/token-swap/anchor/tests/create-pool.ts +++ b/tokens/token-swap/anchor/tests/create-pool.ts @@ -1,10 +1,10 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { PublicKey } from '@solana/web3.js'; -import type { SwapExample } from '../target/types/swap_example'; -import { createValues, expectRevert, mintingTokens, type TestValues } from './utils'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { PublicKey } from "@solana/web3.js"; +import type { SwapExample } from "../target/types/swap_example"; +import { createValues, expectRevert, mintingTokens, type TestValues } from "./utils"; -describe('Create pool', () => { +describe("Create pool", () => { const provider = anchor.AnchorProvider.env(); const connection = provider.connection; anchor.setProvider(provider); @@ -16,7 +16,10 @@ describe('Create pool', () => { beforeEach(async () => { values = createValues(); - await program.methods.createAmm(values.id, values.fee).accounts({ amm: values.ammKey, admin: values.admin.publicKey }).rpc(); + await program.methods + .createAmm(values.id, values.fee) + .accounts({ amm: values.ammKey, admin: values.admin.publicKey }) + .rpc(); await mintingTokens({ connection, @@ -26,7 +29,7 @@ describe('Create pool', () => { }); }); - it('Creation', async () => { + it("Creation", async () => { await program.methods .createPool() .accounts({ @@ -42,7 +45,7 @@ describe('Create pool', () => { .rpc({ skipPreflight: true }); }); - it('Invalid mints', async () => { + it("Invalid mints", async () => { values = createValues({ mintBKeypair: values.mintAKeypair, poolKey: PublicKey.findProgramAddressSync( @@ -50,7 +53,12 @@ describe('Create pool', () => { program.programId, )[0], poolAuthority: PublicKey.findProgramAddressSync( - [values.id.toBuffer(), values.mintAKeypair.publicKey.toBuffer(), values.mintBKeypair.publicKey.toBuffer(), Buffer.from('authority')], + [ + values.id.toBuffer(), + values.mintAKeypair.publicKey.toBuffer(), + values.mintBKeypair.publicKey.toBuffer(), + Buffer.from("authority"), + ], program.programId, )[0], }); diff --git a/tokens/token-swap/anchor/tests/deposit-liquidity.ts b/tokens/token-swap/anchor/tests/deposit-liquidity.ts index 10b6d2fee..edf313ece 100644 --- a/tokens/token-swap/anchor/tests/deposit-liquidity.ts +++ b/tokens/token-swap/anchor/tests/deposit-liquidity.ts @@ -1,10 +1,10 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { expect } from 'chai'; -import type { SwapExample } from '../target/types/swap_example'; -import { createValues, mintingTokens, type TestValues } from './utils'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { expect } from "chai"; +import type { SwapExample } from "../target/types/swap_example"; +import { createValues, mintingTokens, type TestValues } from "./utils"; -describe('Deposit liquidity', () => { +describe("Deposit liquidity", () => { const provider = anchor.AnchorProvider.env(); const connection = provider.connection; anchor.setProvider(provider); @@ -16,7 +16,10 @@ describe('Deposit liquidity', () => { beforeEach(async () => { values = createValues(); - await program.methods.createAmm(values.id, values.fee).accounts({ amm: values.ammKey, admin: values.admin.publicKey }).rpc(); + await program.methods + .createAmm(values.id, values.fee) + .accounts({ amm: values.ammKey, admin: values.admin.publicKey }) + .rpc(); await mintingTokens({ connection, @@ -40,7 +43,7 @@ describe('Deposit liquidity', () => { .rpc(); }); - it('Deposit equal amounts', async () => { + it("Deposit equal amounts", async () => { await program.methods .depositLiquidity(values.depositAmountA, values.depositAmountA) .accounts({ @@ -60,7 +63,9 @@ describe('Deposit liquidity', () => { .rpc({ skipPreflight: true }); const depositTokenAccountLiquditiy = await connection.getTokenAccountBalance(values.liquidityAccount); - expect(depositTokenAccountLiquditiy.value.amount).to.equal(values.depositAmountA.sub(values.minimumLiquidity).toString()); + expect(depositTokenAccountLiquditiy.value.amount).to.equal( + values.depositAmountA.sub(values.minimumLiquidity).toString(), + ); const depositTokenAccountA = await connection.getTokenAccountBalance(values.holderAccountA); expect(depositTokenAccountA.value.amount).to.equal(values.defaultSupply.sub(values.depositAmountA).toString()); const depositTokenAccountB = await connection.getTokenAccountBalance(values.holderAccountB); diff --git a/tokens/token-swap/anchor/tests/swap.ts b/tokens/token-swap/anchor/tests/swap.ts index 71afb6c91..cf415ab67 100644 --- a/tokens/token-swap/anchor/tests/swap.ts +++ b/tokens/token-swap/anchor/tests/swap.ts @@ -1,11 +1,11 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { BN } from 'bn.js'; -import { expect } from 'chai'; -import type { SwapExample } from '../target/types/swap_example'; -import { createValues, mintingTokens, type TestValues } from './utils'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { BN } from "bn.js"; +import { expect } from "chai"; +import type { SwapExample } from "../target/types/swap_example"; +import { createValues, mintingTokens, type TestValues } from "./utils"; -describe('Swap', () => { +describe("Swap", () => { const provider = anchor.AnchorProvider.env(); const connection = provider.connection; anchor.setProvider(provider); @@ -17,7 +17,10 @@ describe('Swap', () => { beforeEach(async () => { values = createValues(); - await program.methods.createAmm(values.id, values.fee).accounts({ amm: values.ammKey, admin: values.admin.publicKey }).rpc(); + await program.methods + .createAmm(values.id, values.fee) + .accounts({ amm: values.ammKey, admin: values.admin.publicKey }) + .rpc(); await mintingTokens({ connection, @@ -59,7 +62,7 @@ describe('Swap', () => { .rpc({ skipPreflight: true }); }); - it('Swap from A to B', async () => { + it("Swap from A to B", async () => { const input = new BN(10 ** 6); await program.methods .swapExactTokensForTokens(true, input, new BN(100)) @@ -80,8 +83,14 @@ describe('Swap', () => { const traderTokenAccountA = await connection.getTokenAccountBalance(values.holderAccountA); const traderTokenAccountB = await connection.getTokenAccountBalance(values.holderAccountB); - expect(traderTokenAccountA.value.amount).to.equal(values.defaultSupply.sub(values.depositAmountA).sub(input).toString()); - expect(Number(traderTokenAccountB.value.amount)).to.be.greaterThan(values.defaultSupply.sub(values.depositAmountB).toNumber()); - expect(Number(traderTokenAccountB.value.amount)).to.be.lessThan(values.defaultSupply.sub(values.depositAmountB).add(input).toNumber()); + expect(traderTokenAccountA.value.amount).to.equal( + values.defaultSupply.sub(values.depositAmountA).sub(input).toString(), + ); + expect(Number(traderTokenAccountB.value.amount)).to.be.greaterThan( + values.defaultSupply.sub(values.depositAmountB).toNumber(), + ); + expect(Number(traderTokenAccountB.value.amount)).to.be.lessThan( + values.defaultSupply.sub(values.depositAmountB).add(input).toNumber(), + ); }); }); diff --git a/tokens/token-swap/anchor/tests/utils.ts b/tokens/token-swap/anchor/tests/utils.ts index 44b0b1079..979338266 100644 --- a/tokens/token-swap/anchor/tests/utils.ts +++ b/tokens/token-swap/anchor/tests/utils.ts @@ -1,7 +1,12 @@ -import * as anchor from '@anchor-lang/core'; -import { createMint, getAssociatedTokenAddressSync, getOrCreateAssociatedTokenAccount, mintTo } from '@solana/spl-token'; -import { type Connection, Keypair, PublicKey, type Signer } from '@solana/web3.js'; -import { BN } from 'bn.js'; +import * as anchor from "@anchor-lang/core"; +import { + createMint, + getAssociatedTokenAddressSync, + getOrCreateAssociatedTokenAccount, + mintTo, +} from "@solana/spl-token"; +import { type Connection, Keypair, PublicKey, type Signer } from "@solana/web3.js"; +import { BN } from "bn.js"; export async function sleep(seconds: number) { new Promise((resolve) => setTimeout(resolve, seconds * 1000)); @@ -11,10 +16,11 @@ export const generateSeededKeypair = (seed: string) => { return Keypair.fromSeed(anchor.utils.bytes.utf8.encode(anchor.utils.sha256.hash(seed)).slice(0, 32)); }; +// biome-ignore lint/suspicious/noExplicitAny: TODO: we should fix this, but we also will move these test to LiteSVM for Anchor 1.0 export const expectRevert = async (promise: Promise) => { try { await promise; - throw new Error('Expected a revert'); + throw new Error("Expected a revert"); } catch { return; } @@ -98,11 +104,11 @@ export function createValues(defaults?: TestValuesDefaults): TestValues { } const poolAuthority = PublicKey.findProgramAddressSync( - [ammKey.toBuffer(), mintAKeypair.publicKey.toBuffer(), mintBKeypair.publicKey.toBuffer(), Buffer.from('authority')], + [ammKey.toBuffer(), mintAKeypair.publicKey.toBuffer(), mintBKeypair.publicKey.toBuffer(), Buffer.from("authority")], anchor.workspace.SwapExample.programId, )[0]; const mintLiquidity = PublicKey.findProgramAddressSync( - [ammKey.toBuffer(), mintAKeypair.publicKey.toBuffer(), mintBKeypair.publicKey.toBuffer(), Buffer.from('liquidity')], + [ammKey.toBuffer(), mintAKeypair.publicKey.toBuffer(), mintBKeypair.publicKey.toBuffer(), Buffer.from("liquidity")], anchor.workspace.SwapExample.programId, )[0]; const poolKey = PublicKey.findProgramAddressSync( diff --git a/tokens/token-swap/anchor/tests/withdraw-liquidity.ts b/tokens/token-swap/anchor/tests/withdraw-liquidity.ts index e2f5ac7f0..33df6ee92 100644 --- a/tokens/token-swap/anchor/tests/withdraw-liquidity.ts +++ b/tokens/token-swap/anchor/tests/withdraw-liquidity.ts @@ -1,10 +1,10 @@ -import type { Program } from '@anchor-lang/core'; -import * as anchor from '@anchor-lang/core'; -import { expect } from 'chai'; -import type { SwapExample } from '../target/types/swap_example'; -import { createValues, mintingTokens, type TestValues } from './utils'; +import type { Program } from "@anchor-lang/core"; +import * as anchor from "@anchor-lang/core"; +import { expect } from "chai"; +import type { SwapExample } from "../target/types/swap_example"; +import { createValues, mintingTokens, type TestValues } from "./utils"; -describe('Withdraw liquidity', () => { +describe("Withdraw liquidity", () => { const provider = anchor.AnchorProvider.env(); const connection = provider.connection; anchor.setProvider(provider); @@ -16,7 +16,10 @@ describe('Withdraw liquidity', () => { beforeEach(async () => { values = createValues(); - await program.methods.createAmm(values.id, values.fee).accounts({ amm: values.ammKey, admin: values.admin.publicKey }).rpc(); + await program.methods + .createAmm(values.id, values.fee) + .accounts({ amm: values.ammKey, admin: values.admin.publicKey }) + .rpc(); await mintingTokens({ connection, @@ -58,7 +61,7 @@ describe('Withdraw liquidity', () => { .rpc({ skipPreflight: true }); }); - it('Withdraw everything', async () => { + it("Withdraw everything", async () => { await program.methods .withdrawLiquidity(values.depositAmountA.sub(values.minimumLiquidity)) .accounts({ @@ -81,10 +84,14 @@ describe('Withdraw liquidity', () => { const liquidityTokenAccount = await connection.getTokenAccountBalance(values.liquidityAccount); const depositTokenAccountA = await connection.getTokenAccountBalance(values.holderAccountA); const depositTokenAccountB = await connection.getTokenAccountBalance(values.holderAccountB); - expect(liquidityTokenAccount.value.amount).to.equal('0'); + expect(liquidityTokenAccount.value.amount).to.equal("0"); expect(Number(depositTokenAccountA.value.amount)).to.be.lessThan(values.defaultSupply.toNumber()); - expect(Number(depositTokenAccountA.value.amount)).to.be.greaterThan(values.defaultSupply.sub(values.depositAmountA).toNumber()); + expect(Number(depositTokenAccountA.value.amount)).to.be.greaterThan( + values.defaultSupply.sub(values.depositAmountA).toNumber(), + ); expect(Number(depositTokenAccountB.value.amount)).to.be.lessThan(values.defaultSupply.toNumber()); - expect(Number(depositTokenAccountB.value.amount)).to.be.greaterThan(values.defaultSupply.sub(values.depositAmountA).toNumber()); + expect(Number(depositTokenAccountB.value.amount)).to.be.greaterThan( + values.defaultSupply.sub(values.depositAmountA).toNumber(), + ); }); }); diff --git a/tokens/transfer-tokens/anchor/Anchor.toml b/tokens/transfer-tokens/anchor/Anchor.toml index 59dd54e57..b8a80f397 100644 --- a/tokens/transfer-tokens/anchor/Anchor.toml +++ b/tokens/transfer-tokens/anchor/Anchor.toml @@ -6,16 +6,13 @@ resolution = true skip-lint = false [programs.localnet] -transfer_tokens = "nHi9DdNjuupjQ3c8AJU9sChB5gLbZvTLsJQouY4hU67" - -# [registry] section removed — no longer used in Anchor 1.0 +transfer_tokens = "FiqULQWZ9mbWaPDiGsms2vLa6H25FCnrtS3sGJHBaCWB" [provider] cluster = "localnet" wallet = "~/.config/solana/id.json" [scripts] -# Only run bankrun tests — the validator tests (test.ts) need Metaplex Token -# Metadata cloned from mainnet which is too slow/unreliable in CI. -# bankrun.test.ts uses a local fixture (tests/fixtures/token_metadata.so). -test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/bankrun.test.ts" +test = "cargo test" + +[hooks] diff --git a/tokens/transfer-tokens/anchor/package.json b/tokens/transfer-tokens/anchor/package.json index 5fce1099c..5bb46b448 100644 --- a/tokens/transfer-tokens/anchor/package.json +++ b/tokens/transfer-tokens/anchor/package.json @@ -1,23 +1,23 @@ { - "type": "module", - "dependencies": { - "@anchor-lang/core": "1.0.0-rc.5", - "@solana/spl-token": "^0.3.8", - "bn.js": "^5.2.1" - }, - "scripts": { - "postinstall": "zx prepare.mjs" - }, - "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "anchor-bankrun": "^0.4.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", - "solana-bankrun": "^0.3.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3", - "zx": "^8.1.4" - } + "type": "module", + "dependencies": { + "@anchor-lang/core": "1.0.0", + "@solana/spl-token": "^0.3.8", + "bn.js": "^5.2.1" + }, + "scripts": { + "postinstall": "zx prepare.mjs" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "anchor-bankrun": "^0.4.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3", + "zx": "^8.1.4" + } } diff --git a/tokens/transfer-tokens/anchor/pnpm-lock.yaml b/tokens/transfer-tokens/anchor/pnpm-lock.yaml index 85e0185a7..20687d0bd 100644 --- a/tokens/transfer-tokens/anchor/pnpm-lock.yaml +++ b/tokens/transfer-tokens/anchor/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@anchor-lang/core': - specifier: 1.0.0-rc.5 - version: 1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) + specifier: 1.0.0 + version: 1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/spl-token': specifier: ^0.3.8 version: 0.3.11(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) @@ -51,18 +51,18 @@ importers: packages: - '@anchor-lang/borsh@1.0.0-rc.5': - resolution: {integrity: sha512-17a+xOmvrn7zSIqlbsjqgz4f64vQEvAmZ7qyQuETCHSskC23LTtjRI0DqAl/r/vC6kosPJGWyOr9ddVIqUVtww==} + '@anchor-lang/borsh@1.0.0': + resolution: {integrity: sha512-kiUd4S/iGKZ4aZvHtX07vNiNnHa/mI/IHmw+0y0sWlvGpPsAWsLXXMrohII5vNCdgZrw+5vVXH9kt836yP9YmQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.69.0 - '@anchor-lang/core@1.0.0-rc.5': - resolution: {integrity: sha512-4iPy4RiEFn6obzYY7zx8IaGAXz2fvJ0uCTF6agAcUBjGNZeypfEb4ZZh6TfLnJy78Lh06JeB7XGqKsaBCMEmQA==} + '@anchor-lang/core@1.0.0': + resolution: {integrity: sha512-YHJQCJNQwF1M1M5VNNOj1DuR7B9v7f/6I9NkFYty7HAbpb3+1HpuDD7nOqI+X3CafXzteWGWZE2kn+Ts7PBKNQ==} engines: {node: '>=17'} - '@anchor-lang/errors@1.0.0-rc.5': - resolution: {integrity: sha512-kLx7oLGVCRhtWeS9PQWGkzZTDpNrGkiJQBrx1rAhEiFemL4YumhUuEbXaaEVuLBt7qZcT1eBPN4LQxYGj3QWyw==} + '@anchor-lang/errors@1.0.0': + resolution: {integrity: sha512-j3ymePewd9Bi6OcXATViRS0IPdPBT8qW4LVM3/hNePH/rZdgi8qDkToiDGuR1fFccfn7t+BrNGudHvcs6JWCFQ==} engines: {node: '>=10'} '@babel/runtime@7.24.5': @@ -923,16 +923,16 @@ packages: snapshots: - '@anchor-lang/borsh@1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@anchor-lang/borsh@1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.1 buffer-layout: 1.2.2 - '@anchor-lang/core@1.0.0-rc.5(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@anchor-lang/core@1.0.0(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@anchor-lang/borsh': 1.0.0-rc.5(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@anchor-lang/errors': 1.0.0-rc.5 + '@anchor-lang/borsh': 1.0.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@anchor-lang/errors': 1.0.0 '@noble/hashes': 1.8.0 '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.3)(utf-8-validate@5.0.10) bn.js: 5.2.1 @@ -950,7 +950,7 @@ snapshots: - typescript - utf-8-validate - '@anchor-lang/errors@1.0.0-rc.5': {} + '@anchor-lang/errors@1.0.0': {} '@babel/runtime@7.24.5': dependencies: diff --git a/tokens/transfer-tokens/anchor/prepare.mjs b/tokens/transfer-tokens/anchor/prepare.mjs index 7c5ec464b..fb6b26225 100644 --- a/tokens/transfer-tokens/anchor/prepare.mjs +++ b/tokens/transfer-tokens/anchor/prepare.mjs @@ -1,17 +1,17 @@ #!/usr/bin/env zx -import { mkdir, rm } from 'node:fs/promises'; -import { join } from 'node:path'; -import { $ } from 'zx'; +import { mkdir, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { $ } from "zx"; const programs = [ { - id: 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', - name: 'token_metadata.so', + id: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", + name: "token_metadata.so", }, ]; -const outputDir = 'tests/fixtures'; +const outputDir = "tests/fixtures"; const overwrite = true; try { diff --git a/tokens/transfer-tokens/anchor/programs/transfer-tokens/Cargo.toml b/tokens/transfer-tokens/anchor/programs/transfer-tokens/Cargo.toml index 3cc201520..85629e982 100644 --- a/tokens/transfer-tokens/anchor/programs/transfer-tokens/Cargo.toml +++ b/tokens/transfer-tokens/anchor/programs/transfer-tokens/Cargo.toml @@ -20,8 +20,15 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = { version = "1.0.0-rc.5", features = ["init-if-needed"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release -anchor-spl = { version = "1.0.0-rc.5", features = ["metadata"] } # Anchor 1.0.0-rc.5 — pin to RC until stable release +anchor-lang = { version = "1.0.0", features = ["init-if-needed"] } +anchor-spl = { version = "1.0.0", features = ["metadata"] } + +[dev-dependencies] +litesvm = "0.11.0" +solana-signer = "3.0.0" +solana-keypair = "3.0.1" +solana-kite = "0.3.0" +borsh = "1.6.1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/transfer-tokens/anchor/programs/transfer-tokens/src/lib.rs b/tokens/transfer-tokens/anchor/programs/transfer-tokens/src/lib.rs index 1c6cdfce7..c1c220219 100644 --- a/tokens/transfer-tokens/anchor/programs/transfer-tokens/src/lib.rs +++ b/tokens/transfer-tokens/anchor/programs/transfer-tokens/src/lib.rs @@ -4,7 +4,7 @@ pub mod instructions; use instructions::*; -declare_id!("nHi9DdNjuupjQ3c8AJU9sChB5gLbZvTLsJQouY4hU67"); +declare_id!("FiqULQWZ9mbWaPDiGsms2vLa6H25FCnrtS3sGJHBaCWB"); #[program] pub mod transfer_tokens { diff --git a/tokens/transfer-tokens/anchor/programs/transfer-tokens/tests/test_transfer_tokens.rs b/tokens/transfer-tokens/anchor/programs/transfer-tokens/tests/test_transfer_tokens.rs new file mode 100644 index 000000000..5a58fa9af --- /dev/null +++ b/tokens/transfer-tokens/anchor/programs/transfer-tokens/tests/test_transfer_tokens.rs @@ -0,0 +1,181 @@ +use { + anchor_lang::{ + solana_program::{instruction::Instruction, pubkey::Pubkey, system_program}, + InstructionData, ToAccountMetas, + }, + litesvm::LiteSVM, + solana_keypair::Keypair, + solana_kite::{create_wallet, get_token_account_balance, send_transaction_from_instructions}, + solana_signer::Signer, +}; + +fn metadata_program_id() -> Pubkey { + "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + .parse() + .unwrap() +} + +fn token_program_id() -> Pubkey { + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + .parse() + .unwrap() +} + +fn associated_token_program_id() -> Pubkey { + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + .parse() + .unwrap() +} + +fn rent_sysvar_id() -> Pubkey { + "SysvarRent111111111111111111111111111111111" + .parse() + .unwrap() +} + +fn derive_metadata_pda(mint: &Pubkey) -> Pubkey { + let metadata_pid = metadata_program_id(); + let (pda, _bump) = Pubkey::find_program_address( + &[b"metadata", metadata_pid.as_ref(), mint.as_ref()], + &metadata_pid, + ); + pda +} + +fn derive_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey { + let (ata, _bump) = Pubkey::find_program_address( + &[ + wallet.as_ref(), + token_program_id().as_ref(), + mint.as_ref(), + ], + &associated_token_program_id(), + ); + ata +} + +fn setup() -> (LiteSVM, Pubkey, Keypair) { + let program_id = transfer_tokens::id(); + let mut svm = LiteSVM::new(); + + let program_bytes = include_bytes!("../../../target/deploy/transfer_tokens.so"); + svm.add_program(program_id, program_bytes).unwrap(); + + let metadata_bytes = include_bytes!("../../../tests/fixtures/mpl_token_metadata.so"); + svm.add_program(metadata_program_id(), metadata_bytes) + .unwrap(); + + let payer = create_wallet(&mut svm, 10_000_000_000).unwrap(); + (svm, program_id, payer) +} + +#[test] +fn test_create_mint_and_transfer() { + let (mut svm, program_id, payer) = setup(); + let mint_keypair = Keypair::new(); + let metadata_account = derive_metadata_pda(&mint_keypair.pubkey()); + + // 1. Create token (with metadata) + let create_ix = Instruction::new_with_bytes( + program_id, + &transfer_tokens::instruction::CreateToken { + token_title: "Solana Gold".to_string(), + token_symbol: "GOLDSOL".to_string(), + token_uri: "https://example.com/token.json".to_string(), + } + .data(), + transfer_tokens::accounts::CreateToken { + payer: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + metadata_account, + token_program: token_program_id(), + token_metadata_program: metadata_program_id(), + system_program: system_program::id(), + rent: rent_sysvar_id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![create_ix], + &[&payer, &mint_keypair], + &payer.pubkey(), + ) + .unwrap(); + + // Verify mint created + let mint_account = svm + .get_account(&mint_keypair.pubkey()) + .expect("Mint should exist"); + assert!(!mint_account.data.is_empty()); + + // 2. Mint tokens (100 tokens to payer's ATA) + svm.expire_blockhash(); + let sender_ata = derive_ata(&payer.pubkey(), &mint_keypair.pubkey()); + + let mint_ix = Instruction::new_with_bytes( + program_id, + &transfer_tokens::instruction::MintToken { amount: 100 }.data(), + transfer_tokens::accounts::MintToken { + mint_authority: payer.pubkey(), + recipient: payer.pubkey(), + mint_account: mint_keypair.pubkey(), + associated_token_account: sender_ata, + token_program: token_program_id(), + associated_token_program: associated_token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![mint_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); + + // Verify tokens minted — 100 * 10^9 = 100_000_000_000 (9 decimals) + assert_eq!( + get_token_account_balance(&svm, &sender_ata).unwrap(), + 100_000_000_000 + ); + + // 3. Transfer tokens (50 tokens to recipient) + svm.expire_blockhash(); + let recipient = Keypair::new(); + let recipient_ata = derive_ata(&recipient.pubkey(), &mint_keypair.pubkey()); + + let transfer_ix = Instruction::new_with_bytes( + program_id, + &transfer_tokens::instruction::TransferTokens { amount: 50 }.data(), + transfer_tokens::accounts::TransferTokens { + sender: payer.pubkey(), + recipient: recipient.pubkey(), + mint_account: mint_keypair.pubkey(), + sender_token_account: sender_ata, + recipient_token_account: recipient_ata, + token_program: token_program_id(), + associated_token_program: associated_token_program_id(), + system_program: system_program::id(), + } + .to_account_metas(None), + ); + send_transaction_from_instructions( + &mut svm, + vec![transfer_ix], + &[&payer], + &payer.pubkey(), + ) + .unwrap(); + + // Verify: sender 50 tokens, recipient 50 tokens (at 9 decimals) + assert_eq!( + get_token_account_balance(&svm, &sender_ata).unwrap(), + 50_000_000_000 + ); + assert_eq!( + get_token_account_balance(&svm, &recipient_ata).unwrap(), + 50_000_000_000 + ); +} diff --git a/tokens/transfer-tokens/anchor/tests/bankrun.test.ts b/tokens/transfer-tokens/anchor/tests/bankrun.test.ts index 175cda746..a0bc25050 100644 --- a/tokens/transfer-tokens/anchor/tests/bankrun.test.ts +++ b/tokens/transfer-tokens/anchor/tests/bankrun.test.ts @@ -8,9 +8,7 @@ import IDL from "../target/idl/transfer_tokens.json"; import type { TransferTokens } from "../target/types/transfer_tokens"; const PROGRAM_ID = new PublicKey(IDL.address); -const METADATA_PROGRAM_ID = new PublicKey( - "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", -); +const METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); describe("Transfer Tokens Bankrun", async () => { const context = await startAnchor( @@ -39,16 +37,10 @@ describe("Transfer Tokens Bankrun", async () => { const recipient = new Keypair(); // Derive the associated token address account for the mint and payer. - const senderTokenAddress = getAssociatedTokenAddressSync( - mintKeypair.publicKey, - payer.publicKey, - ); + const senderTokenAddress = getAssociatedTokenAddressSync(mintKeypair.publicKey, payer.publicKey); // Derive the associated token address account for the mint and recipient. - const recepientTokenAddress = getAssociatedTokenAddressSync( - mintKeypair.publicKey, - recipient.publicKey, - ); + const recepientTokenAddress = getAssociatedTokenAddressSync(mintKeypair.publicKey, recipient.publicKey); it("Create an SPL Token!", async () => { const transactionSignature = await program.methods diff --git a/tokens/transfer-tokens/anchor/tests/fixtures/mpl_token_metadata.so b/tokens/transfer-tokens/anchor/tests/fixtures/mpl_token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/transfer-tokens/anchor/tests/fixtures/mpl_token_metadata.so differ diff --git a/tokens/transfer-tokens/anchor/tests/fixtures/token_metadata.so b/tokens/transfer-tokens/anchor/tests/fixtures/token_metadata.so new file mode 100644 index 000000000..fdebe231b Binary files /dev/null and b/tokens/transfer-tokens/anchor/tests/fixtures/token_metadata.so differ diff --git a/tokens/transfer-tokens/anchor/tests/test.ts b/tokens/transfer-tokens/anchor/tests/test.ts index 4bc0c8213..77a1b0a6d 100644 --- a/tokens/transfer-tokens/anchor/tests/test.ts +++ b/tokens/transfer-tokens/anchor/tests/test.ts @@ -5,87 +5,80 @@ import { BN } from "bn.js"; import type { TransferTokens } from "../target/types/transfer_tokens"; describe("Transfer Tokens", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const payer = provider.wallet as anchor.Wallet; - const program = anchor.workspace - .TransferTokens as anchor.Program; + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const payer = provider.wallet as anchor.Wallet; + const program = anchor.workspace.TransferTokens as anchor.Program; - const metadata = { - name: "Solana Gold", - symbol: "GOLDSOL", - uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", - }; + const metadata = { + name: "Solana Gold", + symbol: "GOLDSOL", + uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", + }; - // Generate new keypair to use as address for mint account. - const mintKeypair = new Keypair(); + // Generate new keypair to use as address for mint account. + const mintKeypair = new Keypair(); - // Generate new keypair to use as address for recipient wallet. - const recipient = new Keypair(); + // Generate new keypair to use as address for recipient wallet. + const recipient = new Keypair(); - // Derive the associated token address account for the mint and payer. - const senderTokenAddress = getAssociatedTokenAddressSync( - mintKeypair.publicKey, - payer.publicKey, - ); + // Derive the associated token address account for the mint and payer. + const senderTokenAddress = getAssociatedTokenAddressSync(mintKeypair.publicKey, payer.publicKey); - // Derive the associated token address account for the mint and recipient. - const recepientTokenAddress = getAssociatedTokenAddressSync( - mintKeypair.publicKey, - recipient.publicKey, - ); + // Derive the associated token address account for the mint and recipient. + const recepientTokenAddress = getAssociatedTokenAddressSync(mintKeypair.publicKey, recipient.publicKey); - it("Create an SPL Token!", async () => { - const transactionSignature = await program.methods - .createToken(metadata.name, metadata.symbol, metadata.uri) - .accounts({ - payer: payer.publicKey, - mintAccount: mintKeypair.publicKey, - }) - .signers([mintKeypair]) - .rpc(); + it("Create an SPL Token!", async () => { + const transactionSignature = await program.methods + .createToken(metadata.name, metadata.symbol, metadata.uri) + .accounts({ + payer: payer.publicKey, + mintAccount: mintKeypair.publicKey, + }) + .signers([mintKeypair]) + .rpc(); - console.log("Success!"); - console.log(` Mint Address: ${mintKeypair.publicKey}`); - console.log(` Transaction Signature: ${transactionSignature}`); - }); + console.log("Success!"); + console.log(` Mint Address: ${mintKeypair.publicKey}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); - it("Mint tokens!", async () => { - // Amount of tokens to mint. - const amount = new BN(100); + it("Mint tokens!", async () => { + // Amount of tokens to mint. + const amount = new BN(100); - // Mint the tokens to the associated token account. - const transactionSignature = await program.methods - .mintToken(amount) - .accounts({ - mintAuthority: payer.publicKey, - recipient: payer.publicKey, - mintAccount: mintKeypair.publicKey, - associatedTokenAccount: senderTokenAddress, - }) - .rpc(); + // Mint the tokens to the associated token account. + const transactionSignature = await program.methods + .mintToken(amount) + .accounts({ + mintAuthority: payer.publicKey, + recipient: payer.publicKey, + mintAccount: mintKeypair.publicKey, + associatedTokenAccount: senderTokenAddress, + }) + .rpc(); - console.log("Success!"); - console.log(` Associated Token Account Address: ${senderTokenAddress}`); - console.log(` Transaction Signature: ${transactionSignature}`); - }); + console.log("Success!"); + console.log(` Associated Token Account Address: ${senderTokenAddress}`); + console.log(` Transaction Signature: ${transactionSignature}`); + }); - it("Transfer tokens!", async () => { - // Amount of tokens to transfer. - const amount = new BN(50); + it("Transfer tokens!", async () => { + // Amount of tokens to transfer. + const amount = new BN(50); - const transactionSignature = await program.methods - .transferTokens(amount) - .accounts({ - sender: payer.publicKey, - recipient: recipient.publicKey, - mintAccount: mintKeypair.publicKey, - senderTokenAccount: senderTokenAddress, - recipientTokenAccount: recepientTokenAddress, - }) - .rpc(); + const transactionSignature = await program.methods + .transferTokens(amount) + .accounts({ + sender: payer.publicKey, + recipient: recipient.publicKey, + mintAccount: mintKeypair.publicKey, + senderTokenAccount: senderTokenAddress, + recipientTokenAccount: recepientTokenAddress, + }) + .rpc(); - console.log("Success!"); - console.log(` Transaction Signature: ${transactionSignature}`); - }); + console.log("Success!"); + console.log(` Transaction Signature: ${transactionSignature}`); + }); }); diff --git a/tokens/transfer-tokens/native/tests/instructions.ts b/tokens/transfer-tokens/native/tests/instructions.ts index c9fa9b36d..6a3d92b20 100644 --- a/tokens/transfer-tokens/native/tests/instructions.ts +++ b/tokens/transfer-tokens/native/tests/instructions.ts @@ -1,4 +1,4 @@ -import * as borsh from 'borsh'; +import * as borsh from "borsh"; export enum MyInstruction { Create = 0, @@ -9,27 +9,27 @@ export enum MyInstruction { export const CreateTokenArgsSchema = { struct: { - instruction: 'u8', - token_title: 'string', - token_symbol: 'string', - token_uri: 'string', - decimals: 'u8', + instruction: "u8", + token_title: "string", + token_symbol: "string", + token_uri: "string", + decimals: "u8", }, }; -export const MintNftArgsSchema = { struct: { instruction: 'u8' } }; +export const MintNftArgsSchema = { struct: { instruction: "u8" } }; export const MintSplArgsSchema = { struct: { - instruction: 'u8', - quantity: 'u64', + instruction: "u8", + quantity: "u64", }, }; export const TransferTokensArgsSchema = { struct: { - instruction: 'u8', - quantity: 'u64', + instruction: "u8", + quantity: "u64", }, }; diff --git a/tokens/transfer-tokens/native/tests/test.ts b/tokens/transfer-tokens/native/tests/test.ts index 10a225c23..cfa947842 100644 --- a/tokens/transfer-tokens/native/tests/test.ts +++ b/tokens/transfer-tokens/native/tests/test.ts @@ -1,6 +1,6 @@ -import { Buffer } from 'node:buffer'; -import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from '@metaplex-foundation/mpl-token-metadata'; -import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from '@solana/spl-token'; +import { Buffer } from "node:buffer"; +import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata"; +import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from "@solana/spl-token"; import { Connection, Keypair, @@ -10,36 +10,44 @@ import { sendAndConfirmTransaction, Transaction, TransactionInstruction, -} from '@solana/web3.js'; -import { BN } from 'bn.js'; -import { borshSerialize, CreateTokenArgsSchema, MintNftArgsSchema, MintSplArgsSchema, TransferTokensArgsSchema, MyInstruction } from './instructions'; +} from "@solana/web3.js"; +import { BN } from "bn.js"; +import { + borshSerialize, + CreateTokenArgsSchema, + MintNftArgsSchema, + MintSplArgsSchema, + MyInstruction, + TransferTokensArgsSchema, +} from "./instructions"; function createKeypairFromFile(path: string): Keypair { - return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require('node:fs').readFileSync(path, 'utf-8')))); + return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(require("node:fs").readFileSync(path, "utf-8")))); } -describe('Transferring Tokens', async () => { +describe("Transferring Tokens", async () => { // const connection = new Connection(`http://localhost:8899`, 'confirmed'); - const connection = new Connection('https://api.devnet.solana.com/', 'confirmed'); - const payer = createKeypairFromFile(`${require('node:os').homedir()}/.config/solana/id.json`); - const program = createKeypairFromFile('./program/target/deploy/program-keypair.json'); + const connection = new Connection("https://api.devnet.solana.com/", "confirmed"); + const payer = createKeypairFromFile(`${require("node:os").homedir()}/.config/solana/id.json`); + const program = createKeypairFromFile("./program/target/deploy/program-keypair.json"); const tokenMintKeypair: Keypair = Keypair.generate(); const nftMintKeypair: Keypair = Keypair.generate(); const recipientWallet = Keypair.generate(); - it('Create an SPL Token!', async () => { + it("Create an SPL Token!", async () => { const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), tokenMintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), tokenMintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; const instructionData = borshSerialize(CreateTokenArgsSchema, { instruction: MyInstruction.Create, - token_title: 'Solana Gold', - token_symbol: 'GOLDSOL', - token_uri: 'https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json', + token_title: "Solana Gold", + token_symbol: "GOLDSOL", + token_uri: + "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", decimals: 9, }); @@ -68,22 +76,23 @@ describe('Transferring Tokens', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, tokenMintKeypair]); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${tokenMintKeypair.publicKey}`); console.log(` Tx Signature: ${sx}`); }); - it('Create an NFT!', async () => { + it("Create an NFT!", async () => { const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nftMintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nftMintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; const instructionData = borshSerialize(CreateTokenArgsSchema, { instruction: MyInstruction.Create, - token_title: 'Homer NFT', - token_symbol: 'HOMR', - token_uri: 'https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json', + token_title: "Homer NFT", + token_symbol: "HOMR", + token_uri: + "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json", decimals: 0, }); @@ -108,12 +117,12 @@ describe('Transferring Tokens', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, nftMintKeypair]); - console.log('Success!'); + console.log("Success!"); console.log(` Mint Address: ${nftMintKeypair.publicKey}`); console.log(` Tx Signature: ${sx}`); }); - it('Mint some tokens to your wallet!', async () => { + it("Mint some tokens to your wallet!", async () => { const associatedTokenAccountAddress = await getAssociatedTokenAddress(tokenMintKeypair.publicKey, payer.publicKey); const instructionData = borshSerialize(MintSplArgsSchema, { @@ -149,19 +158,24 @@ describe('Transferring Tokens', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]); - console.log('Success!'); + console.log("Success!"); console.log(` ATA Address: ${associatedTokenAccountAddress}`); console.log(` Tx Signature: ${sx}`); }); - it('Mint the NFT to your wallet!', async () => { + it("Mint the NFT to your wallet!", async () => { const metadataAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nftMintKeypair.publicKey.toBuffer()], + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nftMintKeypair.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID, )[0]; const editionAddress = PublicKey.findProgramAddressSync( - [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nftMintKeypair.publicKey.toBuffer(), Buffer.from('edition')], + [ + Buffer.from("metadata"), + TOKEN_METADATA_PROGRAM_ID.toBuffer(), + nftMintKeypair.publicKey.toBuffer(), + Buffer.from("edition"), + ], TOKEN_METADATA_PROGRAM_ID, )[0]; @@ -203,22 +217,25 @@ describe('Transferring Tokens', async () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer]); - console.log('Success!'); + console.log("Success!"); console.log(` ATA Address: ${associatedTokenAccountAddress}`); console.log(` Tx Signature: ${sx}`); }); - it('Prep a new test wallet for transfers', async () => { + it("Prep a new test wallet for transfers", async () => { await connection.confirmTransaction( await connection.requestAirdrop(recipientWallet.publicKey, await connection.getMinimumBalanceForRentExemption(0)), ); console.log(`Recipient Pubkey: ${recipientWallet.publicKey}`); }); - it('Transfer tokens to another wallet!', async () => { + it("Transfer tokens to another wallet!", async () => { const fromAssociatedTokenAddress = await getAssociatedTokenAddress(tokenMintKeypair.publicKey, payer.publicKey); console.log(`Owner Token Address: ${fromAssociatedTokenAddress}`); - const toAssociatedTokenAddress = await getAssociatedTokenAddress(tokenMintKeypair.publicKey, recipientWallet.publicKey); + const toAssociatedTokenAddress = await getAssociatedTokenAddress( + tokenMintKeypair.publicKey, + recipientWallet.publicKey, + ); console.log(`Recipient Token Address: ${toAssociatedTokenAddress}`); const transferToInstructionData = borshSerialize(TransferTokensArgsSchema, { @@ -254,13 +271,18 @@ describe('Transferring Tokens', async () => { data: transferToInstructionData, }); - await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, recipientWallet], { skipPreflight: true }); + await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, recipientWallet], { + skipPreflight: true, + }); }); - it('Transfer NFT to another wallet!', async () => { + it("Transfer NFT to another wallet!", async () => { const fromAssociatedTokenAddress = await getAssociatedTokenAddress(nftMintKeypair.publicKey, payer.publicKey); console.log(`Owner Token Address: ${fromAssociatedTokenAddress}`); - const toAssociatedTokenAddress = await getAssociatedTokenAddress(nftMintKeypair.publicKey, recipientWallet.publicKey); + const toAssociatedTokenAddress = await getAssociatedTokenAddress( + nftMintKeypair.publicKey, + recipientWallet.publicKey, + ); console.log(`Recipient Token Address: ${toAssociatedTokenAddress}`); const transferToInstructionData = borshSerialize(TransferTokensArgsSchema, { @@ -292,6 +314,8 @@ describe('Transferring Tokens', async () => { data: transferToInstructionData, }); - await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, recipientWallet], { skipPreflight: true }); + await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer, recipientWallet], { + skipPreflight: true, + }); }); }); diff --git a/tools/shank-and-solita/native/.solitarc.js b/tools/shank-and-solita/native/.solitarc.js index e42bad663..a02dc623f 100644 --- a/tools/shank-and-solita/native/.solitarc.js +++ b/tools/shank-and-solita/native/.solitarc.js @@ -1,12 +1,12 @@ -const path = require('node:path'); -const programDir = path.join(__dirname, 'program'); -const idlDir = path.join(programDir, 'idl'); -const sdkDir = path.join(__dirname, 'tests', 'generated'); -const binaryInstallDir = path.join(__dirname, '.crates'); +const path = require("node:path"); +const programDir = path.join(__dirname, "program"); +const idlDir = path.join(programDir, "idl"); +const sdkDir = path.join(__dirname, "tests", "generated"); +const binaryInstallDir = path.join(__dirname, ".crates"); module.exports = { - idlGenerator: 'shank', - programName: 'car_rental_service', + idlGenerator: "shank", + programName: "car_rental_service", idlDir, sdkDir, binaryInstallDir, diff --git a/tools/shank-and-solita/native/tests/generated/accounts/Car.ts b/tools/shank-and-solita/native/tests/generated/accounts/Car.ts index 5d67a76f2..9b046922d 100644 --- a/tools/shank-and-solita/native/tests/generated/accounts/Car.ts +++ b/tools/shank-and-solita/native/tests/generated/accounts/Car.ts @@ -5,9 +5,9 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; -import * as beetSolana from '@metaplex-foundation/beet-solana'; -import * as web3 from '@solana/web3.js'; +import * as beet from "@metaplex-foundation/beet"; +import * as beetSolana from "@metaplex-foundation/beet-solana"; +import * as web3 from "@solana/web3.js"; /** * Arguments used to create {@link Car} @@ -72,7 +72,7 @@ export class Car implements CarArgs { * * @param programId - the program that owns the accounts we are filtering */ - static gpaBuilder(programId: web3.PublicKey = new web3.PublicKey('8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ')) { + static gpaBuilder(programId: web3.PublicKey = new web3.PublicKey("8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ")) { return beetSolana.GpaBuilder.fromStruct(programId, carBeet); } @@ -112,7 +112,11 @@ export class Car implements CarArgs { * depends on them * @param connection used to retrieve the rent exemption information */ - static async getMinimumBalanceForRentExemption(args: CarArgs, connection: web3.Connection, commitment?: web3.Commitment): Promise { + static async getMinimumBalanceForRentExemption( + args: CarArgs, + connection: web3.Connection, + commitment?: web3.Commitment, + ): Promise { return connection.getMinimumBalanceForRentExemption(Car.byteSize(args), commitment); } @@ -135,10 +139,10 @@ export class Car implements CarArgs { */ export const carBeet = new beet.FixableBeetStruct( [ - ['year', beet.u16], - ['make', beet.utf8String], - ['model', beet.utf8String], + ["year", beet.u16], + ["make", beet.utf8String], + ["model", beet.utf8String], ], Car.fromArgs, - 'Car', + "Car", ); diff --git a/tools/shank-and-solita/native/tests/generated/accounts/RentalOrder.ts b/tools/shank-and-solita/native/tests/generated/accounts/RentalOrder.ts index ea2923a74..458861608 100644 --- a/tools/shank-and-solita/native/tests/generated/accounts/RentalOrder.ts +++ b/tools/shank-and-solita/native/tests/generated/accounts/RentalOrder.ts @@ -5,10 +5,10 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; -import * as beetSolana from '@metaplex-foundation/beet-solana'; -import * as web3 from '@solana/web3.js'; -import { RentalOrderStatus, rentalOrderStatusBeet } from '../types/RentalOrderStatus'; +import * as beet from "@metaplex-foundation/beet"; +import * as beetSolana from "@metaplex-foundation/beet-solana"; +import * as web3 from "@solana/web3.js"; +import { RentalOrderStatus, rentalOrderStatusBeet } from "../types/RentalOrderStatus"; /** * Arguments used to create {@link RentalOrder} @@ -79,7 +79,7 @@ export class RentalOrder implements RentalOrderArgs { * * @param programId - the program that owns the accounts we are filtering */ - static gpaBuilder(programId: web3.PublicKey = new web3.PublicKey('8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ')) { + static gpaBuilder(programId: web3.PublicKey = new web3.PublicKey("8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ")) { return beetSolana.GpaBuilder.fromStruct(programId, rentalOrderBeet); } @@ -119,7 +119,11 @@ export class RentalOrder implements RentalOrderArgs { * depends on them * @param connection used to retrieve the rent exemption information */ - static async getMinimumBalanceForRentExemption(args: RentalOrderArgs, connection: web3.Connection, commitment?: web3.Commitment): Promise { + static async getMinimumBalanceForRentExemption( + args: RentalOrderArgs, + connection: web3.Connection, + commitment?: web3.Commitment, + ): Promise { return connection.getMinimumBalanceForRentExemption(RentalOrder.byteSize(args), commitment); } @@ -135,7 +139,7 @@ export class RentalOrder implements RentalOrderArgs { returnDate: this.returnDate, price: (() => { const x = <{ toNumber: () => number }>this.price; - if (typeof x.toNumber === 'function') { + if (typeof x.toNumber === "function") { try { return x.toNumber(); } catch (_) { @@ -155,13 +159,13 @@ export class RentalOrder implements RentalOrderArgs { */ export const rentalOrderBeet = new beet.FixableBeetStruct( [ - ['car', beetSolana.publicKey], - ['name', beet.utf8String], - ['pickUpDate', beet.utf8String], - ['returnDate', beet.utf8String], - ['price', beet.u64], - ['status', rentalOrderStatusBeet], + ["car", beetSolana.publicKey], + ["name", beet.utf8String], + ["pickUpDate", beet.utf8String], + ["returnDate", beet.utf8String], + ["price", beet.u64], + ["status", rentalOrderStatusBeet], ], RentalOrder.fromArgs, - 'RentalOrder', + "RentalOrder", ); diff --git a/tools/shank-and-solita/native/tests/generated/accounts/index.ts b/tools/shank-and-solita/native/tests/generated/accounts/index.ts index 7c593175c..6b514469d 100644 --- a/tools/shank-and-solita/native/tests/generated/accounts/index.ts +++ b/tools/shank-and-solita/native/tests/generated/accounts/index.ts @@ -1,7 +1,7 @@ -export * from './Car'; -export * from './RentalOrder'; +export * from "./Car"; +export * from "./RentalOrder"; -import { Car } from './Car'; -import { RentalOrder } from './RentalOrder'; +import { Car } from "./Car"; +import { RentalOrder } from "./RentalOrder"; export const accountProviders = { Car, RentalOrder }; diff --git a/tools/shank-and-solita/native/tests/generated/index.ts b/tools/shank-and-solita/native/tests/generated/index.ts index 046f79c19..deb4a0914 100644 --- a/tools/shank-and-solita/native/tests/generated/index.ts +++ b/tools/shank-and-solita/native/tests/generated/index.ts @@ -1,8 +1,8 @@ -import { PublicKey } from '@solana/web3.js'; +import { PublicKey } from "@solana/web3.js"; -export * from './accounts'; -export * from './instructions'; -export * from './types'; +export * from "./accounts"; +export * from "./instructions"; +export * from "./types"; /** * Program address @@ -10,7 +10,7 @@ export * from './types'; * @category constants * @category generated */ -export const PROGRAM_ADDRESS = '8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ'; +export const PROGRAM_ADDRESS = "8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ"; /** * Program public key diff --git a/tools/shank-and-solita/native/tests/generated/instructions/AddCar.ts b/tools/shank-and-solita/native/tests/generated/instructions/AddCar.ts index d5cd995da..38a644edb 100644 --- a/tools/shank-and-solita/native/tests/generated/instructions/AddCar.ts +++ b/tools/shank-and-solita/native/tests/generated/instructions/AddCar.ts @@ -5,9 +5,9 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; -import * as web3 from '@solana/web3.js'; -import { type AddCarArgs, addCarArgsBeet } from '../types/AddCarArgs'; +import * as beet from "@metaplex-foundation/beet"; +import * as web3 from "@solana/web3.js"; +import { type AddCarArgs, addCarArgsBeet } from "../types/AddCarArgs"; /** * @category Instructions @@ -28,10 +28,10 @@ export const AddCarStruct = new beet.FixableBeetArgsStruct< } >( [ - ['instructionDiscriminator', beet.u8], - ['addCarArgs', addCarArgsBeet], + ["instructionDiscriminator", beet.u8], + ["addCarArgs", addCarArgsBeet], ], - 'AddCarInstructionArgs', + "AddCarInstructionArgs", ); /** * Accounts required by the _AddCar_ instruction @@ -63,7 +63,7 @@ export const addCarInstructionDiscriminator = 0; export function createAddCarInstruction( accounts: AddCarInstructionAccounts, args: AddCarInstructionArgs, - programId = new web3.PublicKey('8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ'), + programId = new web3.PublicKey("8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ"), ) { const [data] = AddCarStruct.serialize({ instructionDiscriminator: addCarInstructionDiscriminator, diff --git a/tools/shank-and-solita/native/tests/generated/instructions/BookRental.ts b/tools/shank-and-solita/native/tests/generated/instructions/BookRental.ts index 1e6bb23de..4b2ec9e2a 100644 --- a/tools/shank-and-solita/native/tests/generated/instructions/BookRental.ts +++ b/tools/shank-and-solita/native/tests/generated/instructions/BookRental.ts @@ -5,9 +5,9 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; -import * as web3 from '@solana/web3.js'; -import { type BookRentalArgs, bookRentalArgsBeet } from '../types/BookRentalArgs'; +import * as beet from "@metaplex-foundation/beet"; +import * as web3 from "@solana/web3.js"; +import { type BookRentalArgs, bookRentalArgsBeet } from "../types/BookRentalArgs"; /** * @category Instructions @@ -28,10 +28,10 @@ export const BookRentalStruct = new beet.FixableBeetArgsStruct< } >( [ - ['instructionDiscriminator', beet.u8], - ['bookRentalArgs', bookRentalArgsBeet], + ["instructionDiscriminator", beet.u8], + ["bookRentalArgs", bookRentalArgsBeet], ], - 'BookRentalInstructionArgs', + "BookRentalInstructionArgs", ); /** * Accounts required by the _BookRental_ instruction @@ -65,7 +65,7 @@ export const bookRentalInstructionDiscriminator = 1; export function createBookRentalInstruction( accounts: BookRentalInstructionAccounts, args: BookRentalInstructionArgs, - programId = new web3.PublicKey('8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ'), + programId = new web3.PublicKey("8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ"), ) { const [data] = BookRentalStruct.serialize({ instructionDiscriminator: bookRentalInstructionDiscriminator, diff --git a/tools/shank-and-solita/native/tests/generated/instructions/PickUpCar.ts b/tools/shank-and-solita/native/tests/generated/instructions/PickUpCar.ts index f0fced5fa..329a6fce7 100644 --- a/tools/shank-and-solita/native/tests/generated/instructions/PickUpCar.ts +++ b/tools/shank-and-solita/native/tests/generated/instructions/PickUpCar.ts @@ -5,8 +5,8 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; -import * as web3 from '@solana/web3.js'; +import * as beet from "@metaplex-foundation/beet"; +import * as web3 from "@solana/web3.js"; /** * @category Instructions @@ -15,7 +15,7 @@ import * as web3 from '@solana/web3.js'; */ export const PickUpCarStruct = new beet.BeetArgsStruct<{ instructionDiscriminator: number; -}>([['instructionDiscriminator', beet.u8]], 'PickUpCarInstructionArgs'); +}>([["instructionDiscriminator", beet.u8]], "PickUpCarInstructionArgs"); /** * Accounts required by the _PickUpCar_ instruction * @@ -44,7 +44,7 @@ export const pickUpCarInstructionDiscriminator = 2; */ export function createPickUpCarInstruction( accounts: PickUpCarInstructionAccounts, - programId = new web3.PublicKey('8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ'), + programId = new web3.PublicKey("8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ"), ) { const [data] = PickUpCarStruct.serialize({ instructionDiscriminator: pickUpCarInstructionDiscriminator, diff --git a/tools/shank-and-solita/native/tests/generated/instructions/ReturnCar.ts b/tools/shank-and-solita/native/tests/generated/instructions/ReturnCar.ts index db3d7f303..1a7dc0e00 100644 --- a/tools/shank-and-solita/native/tests/generated/instructions/ReturnCar.ts +++ b/tools/shank-and-solita/native/tests/generated/instructions/ReturnCar.ts @@ -5,8 +5,8 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; -import * as web3 from '@solana/web3.js'; +import * as beet from "@metaplex-foundation/beet"; +import * as web3 from "@solana/web3.js"; /** * @category Instructions @@ -15,7 +15,7 @@ import * as web3 from '@solana/web3.js'; */ export const ReturnCarStruct = new beet.BeetArgsStruct<{ instructionDiscriminator: number; -}>([['instructionDiscriminator', beet.u8]], 'ReturnCarInstructionArgs'); +}>([["instructionDiscriminator", beet.u8]], "ReturnCarInstructionArgs"); /** * Accounts required by the _ReturnCar_ instruction * @@ -44,7 +44,7 @@ export const returnCarInstructionDiscriminator = 3; */ export function createReturnCarInstruction( accounts: ReturnCarInstructionAccounts, - programId = new web3.PublicKey('8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ'), + programId = new web3.PublicKey("8avNGHVXDwsELJaWMSoUZ44CirQd4zyU9Ez4ZmP4jNjZ"), ) { const [data] = ReturnCarStruct.serialize({ instructionDiscriminator: returnCarInstructionDiscriminator, diff --git a/tools/shank-and-solita/native/tests/generated/instructions/index.ts b/tools/shank-and-solita/native/tests/generated/instructions/index.ts index 86e06563b..f15225432 100644 --- a/tools/shank-and-solita/native/tests/generated/instructions/index.ts +++ b/tools/shank-and-solita/native/tests/generated/instructions/index.ts @@ -1,4 +1,4 @@ -export * from './AddCar'; -export * from './BookRental'; -export * from './PickUpCar'; -export * from './ReturnCar'; +export * from "./AddCar"; +export * from "./BookRental"; +export * from "./PickUpCar"; +export * from "./ReturnCar"; diff --git a/tools/shank-and-solita/native/tests/generated/types/AddCarArgs.ts b/tools/shank-and-solita/native/tests/generated/types/AddCarArgs.ts index ba0f0fae2..72be60649 100644 --- a/tools/shank-and-solita/native/tests/generated/types/AddCarArgs.ts +++ b/tools/shank-and-solita/native/tests/generated/types/AddCarArgs.ts @@ -5,7 +5,7 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; +import * as beet from "@metaplex-foundation/beet"; export type AddCarArgs = { year: number; make: string; @@ -18,9 +18,9 @@ export type AddCarArgs = { */ export const addCarArgsBeet = new beet.FixableBeetArgsStruct( [ - ['year', beet.u16], - ['make', beet.utf8String], - ['model', beet.utf8String], + ["year", beet.u16], + ["make", beet.utf8String], + ["model", beet.utf8String], ], - 'AddCarArgs', + "AddCarArgs", ); diff --git a/tools/shank-and-solita/native/tests/generated/types/BookRentalArgs.ts b/tools/shank-and-solita/native/tests/generated/types/BookRentalArgs.ts index b1088ead6..f236b7efa 100644 --- a/tools/shank-and-solita/native/tests/generated/types/BookRentalArgs.ts +++ b/tools/shank-and-solita/native/tests/generated/types/BookRentalArgs.ts @@ -5,7 +5,7 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; +import * as beet from "@metaplex-foundation/beet"; export type BookRentalArgs = { name: string; pickUpDate: string; @@ -19,10 +19,10 @@ export type BookRentalArgs = { */ export const bookRentalArgsBeet = new beet.FixableBeetArgsStruct( [ - ['name', beet.utf8String], - ['pickUpDate', beet.utf8String], - ['returnDate', beet.utf8String], - ['price', beet.u64], + ["name", beet.utf8String], + ["pickUpDate", beet.utf8String], + ["returnDate", beet.utf8String], + ["price", beet.u64], ], - 'BookRentalArgs', + "BookRentalArgs", ); diff --git a/tools/shank-and-solita/native/tests/generated/types/RentalOrderStatus.ts b/tools/shank-and-solita/native/tests/generated/types/RentalOrderStatus.ts index 52a96ab23..66d5f5a15 100644 --- a/tools/shank-and-solita/native/tests/generated/types/RentalOrderStatus.ts +++ b/tools/shank-and-solita/native/tests/generated/types/RentalOrderStatus.ts @@ -5,7 +5,7 @@ * See: https://github.com/metaplex-foundation/solita */ -import * as beet from '@metaplex-foundation/beet'; +import * as beet from "@metaplex-foundation/beet"; /** * @category enums * @category generated @@ -20,4 +20,7 @@ export enum RentalOrderStatus { * @category userTypes * @category generated */ -export const rentalOrderStatusBeet = beet.fixedScalarEnum(RentalOrderStatus) as beet.FixedSizeBeet; +export const rentalOrderStatusBeet = beet.fixedScalarEnum(RentalOrderStatus) as beet.FixedSizeBeet< + RentalOrderStatus, + RentalOrderStatus +>; diff --git a/tools/shank-and-solita/native/tests/generated/types/index.ts b/tools/shank-and-solita/native/tests/generated/types/index.ts index 2e86601ee..dc2300b8e 100644 --- a/tools/shank-and-solita/native/tests/generated/types/index.ts +++ b/tools/shank-and-solita/native/tests/generated/types/index.ts @@ -1,3 +1,3 @@ -export * from './AddCarArgs'; -export * from './BookRentalArgs'; -export * from './RentalOrderStatus'; +export * from "./AddCarArgs"; +export * from "./BookRentalArgs"; +export * from "./RentalOrderStatus"; diff --git a/tools/shank-and-solita/native/tests/test.ts b/tools/shank-and-solita/native/tests/test.ts index 3fa66a96f..b1ab61acf 100644 --- a/tools/shank-and-solita/native/tests/test.ts +++ b/tools/shank-and-solita/native/tests/test.ts @@ -1,5 +1,5 @@ -import { Connection, Keypair, PublicKey, SystemProgram, sendAndConfirmTransaction, Transaction } from '@solana/web3.js'; -import { describe, it } from 'mocha'; +import { Connection, Keypair, PublicKey, SystemProgram, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; +import { describe, it } from "mocha"; import { type AddCarArgs, Car, @@ -9,42 +9,42 @@ import { createReturnCarInstruction, RentalOrder, RentalOrderStatus, -} from './generated'; +} from "./generated"; function loadKeypairFromFile(path: string): Keypair { - return Keypair.fromSecretKey(Buffer.from(JSON.parse(require('node:fs').readFileSync(path, 'utf-8')))); + return Keypair.fromSecretKey(Buffer.from(JSON.parse(require("node:fs").readFileSync(path, "utf-8")))); } const carBmw: AddCarArgs = { year: 2020, - make: 'BMW', - model: 'iX1', + make: "BMW", + model: "iX1", }; const carMercedes: AddCarArgs = { year: 2019, - make: 'Mercedes-Benz', - model: 'EQS', + make: "Mercedes-Benz", + model: "EQS", }; const rentalInfo = { - name: 'Fred Flinstone', - pickUpDate: '01/28/2023 8:00 AM', - returnDate: '01/28/2023 10:00 PM', + name: "Fred Flinstone", + pickUpDate: "01/28/2023 8:00 AM", + returnDate: "01/28/2023 10:00 PM", price: 300, }; -describe('Car Rental Service', () => { - const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); - const payer = loadKeypairFromFile(`${require('node:os').homedir()}/.config/solana/id.json`); - const program = loadKeypairFromFile('./program/target/deploy/car_rental_service-keypair.json'); +describe("Car Rental Service", () => { + const connection = new Connection("https://api.devnet.solana.com", "confirmed"); + const payer = loadKeypairFromFile(`${require("node:os").homedir()}/.config/solana/id.json`); + const program = loadKeypairFromFile("./program/target/deploy/car_rental_service-keypair.json"); let bmwPublicKey: PublicKey; let _mercedesPublicKey: PublicKey; async function createCar(car: AddCarArgs): Promise { const carAccountPublicKey = PublicKey.findProgramAddressSync( - [Buffer.from('car'), Buffer.from(car.make), Buffer.from(car.model)], + [Buffer.from("car"), Buffer.from(car.make), Buffer.from(car.model)], program.publicKey, )[0]; const ix = createAddCarInstruction( @@ -58,31 +58,31 @@ describe('Car Rental Service', () => { const sx = await sendAndConfirmTransaction(connection, new Transaction().add(ix), [payer], { skipPreflight: true }); await connection.confirmTransaction(sx); const carData = await Car.fromAccountAddress(connection, carAccountPublicKey); - console.log('New car created:'); + console.log("New car created:"); console.log(` Year : ${carData.year}`); console.log(` Make : ${carData.make}`); console.log(` Model : ${carData.model}`); return carAccountPublicKey; } - it('Create a car that can be rented', async () => { + it("Create a car that can be rented", async () => { bmwPublicKey = await createCar(carBmw); }); - it('Create another car that can be rented', async () => { + it("Create another car that can be rented", async () => { _mercedesPublicKey = await createCar(carMercedes); }); const evaluateStatus = (status: RentalOrderStatus): string => { - if (status === RentalOrderStatus.Created) return 'Created'; - if (status === RentalOrderStatus.PickedUp) return 'Picked Up'; - return 'Returned'; + if (status === RentalOrderStatus.Created) return "Created"; + if (status === RentalOrderStatus.PickedUp) return "Picked Up"; + return "Returned"; }; async function printRentalDetails(rentalPublicKey: PublicKey, carPublicKey: PublicKey) { const rentalData = await RentalOrder.fromAccountAddress(connection, rentalPublicKey); const carData = await Car.fromAccountAddress(connection, carPublicKey); - console.log('Rental booked:'); - console.log(' Vehicle details:'); + console.log("Rental booked:"); + console.log(" Vehicle details:"); console.log(` Year : ${carData.year}`); console.log(` Make : ${carData.make}`); console.log(` Model : ${carData.model}`); @@ -93,9 +93,9 @@ describe('Car Rental Service', () => { console.log(` Status : ${evaluateStatus(rentalData.status)}`); } - it('Book a new rental', async () => { + it("Book a new rental", async () => { const rentalAccountPublicKey = PublicKey.findProgramAddressSync( - [Buffer.from('rental_order'), bmwPublicKey.toBuffer(), payer.publicKey.toBuffer()], + [Buffer.from("rental_order"), bmwPublicKey.toBuffer(), payer.publicKey.toBuffer()], program.publicKey, )[0]; const ix = createBookRentalInstruction( @@ -114,9 +114,9 @@ describe('Car Rental Service', () => { await printRentalDetails(rentalAccountPublicKey, bmwPublicKey); }); - it('Pick up your rental car', async () => { + it("Pick up your rental car", async () => { const rentalAccountPublicKey = PublicKey.findProgramAddressSync( - [Buffer.from('rental_order'), bmwPublicKey.toBuffer(), payer.publicKey.toBuffer()], + [Buffer.from("rental_order"), bmwPublicKey.toBuffer(), payer.publicKey.toBuffer()], program.publicKey, )[0]; const ix = createPickUpCarInstruction({ @@ -129,9 +129,9 @@ describe('Car Rental Service', () => { await printRentalDetails(rentalAccountPublicKey, bmwPublicKey); }); - it('Return your rental car', async () => { + it("Return your rental car", async () => { const rentalAccountPublicKey = PublicKey.findProgramAddressSync( - [Buffer.from('rental_order'), bmwPublicKey.toBuffer(), payer.publicKey.toBuffer()], + [Buffer.from("rental_order"), bmwPublicKey.toBuffer(), payer.publicKey.toBuffer()], program.publicKey, )[0]; const ix = createReturnCarInstruction({ diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index a46b42c19..000000000 --- a/yarn.lock +++ /dev/null @@ -1,153 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@biomejs/biome@1.7.3": - version "1.7.3" - resolved "https://registry.npmjs.org/@biomejs/biome/-/biome-1.7.3.tgz" - integrity sha512-ogFQI+fpXftr+tiahA6bIXwZ7CSikygASdqMtH07J2cUzrpjyTMVc9Y97v23c7/tL1xCZhM+W9k4hYIBm7Q6cQ== - optionalDependencies: - "@biomejs/cli-darwin-arm64" "1.7.3" - "@biomejs/cli-darwin-x64" "1.7.3" - "@biomejs/cli-linux-arm64" "1.7.3" - "@biomejs/cli-linux-arm64-musl" "1.7.3" - "@biomejs/cli-linux-x64" "1.7.3" - "@biomejs/cli-linux-x64-musl" "1.7.3" - "@biomejs/cli-win32-arm64" "1.7.3" - "@biomejs/cli-win32-x64" "1.7.3" - -"@biomejs/cli-darwin-arm64@1.7.3": - version "1.7.3" - resolved "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.7.3.tgz" - integrity sha512-eDvLQWmGRqrPIRY7AIrkPHkQ3visEItJKkPYSHCscSDdGvKzYjmBJwG1Gu8+QC5ed6R7eiU63LEC0APFBobmfQ== - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.1" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.15" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@tsconfig/node10@^1.0.7": - version "1.0.9" - resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz" - integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.4" - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== - -"@types/node@*", "@types/node@^20.9.0": - version "20.9.0" - resolved "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz" - integrity sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw== - dependencies: - undici-types "~5.26.4" - -acorn-walk@^8.1.1: - version "8.3.0" - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz" - integrity sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA== - -acorn@^8.4.1: - version "8.11.2" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz" - integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -husky@^9.0.11: - version "9.0.11" - resolved "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz" - integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw== - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -ts-node@^10.9.1: - version "10.9.1" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz" - integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -typescript@^5.2.2, typescript@>=2.7: - version "5.2.2" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz" - integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==