diff --git a/Cargo.lock b/Cargo.lock index d92d1b032..83049dc2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1128,6 +1128,16 @@ dependencies = [ "anchor-lang", ] +[[package]] +name = "create-token-pinocchio-program" +version = "0.1.0" +dependencies = [ + "pinocchio 0.10.2", + "pinocchio-log", + "pinocchio-system", + "pinocchio-token", +] + [[package]] name = "cross-program-invocation-pinocchio-hand" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index aae171e04..77848356c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ members = [ "basics/transfer-sol/asm", # tokens + "tokens/create-token/pinocchio/program", "tokens/escrow/pinocchio/program", "tokens/transfer-tokens/pinocchio/program", "tokens/token-2022/mint-close-authority/native/program", diff --git a/README.md b/README.md index 0f7048fa8..dec266ca7 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ How to store state that changes size in Solana. [Create a token on Solana with a token symbol and icon.](./tokens/create-token/README.md) -[anchor](./tokens/create-token/anchor) [native](./tokens/create-token/native) +[anchor](./tokens/create-token/anchor) [pinocchio](./tokens/create-token/pinocchio) [native](./tokens/create-token/native) ### Minting NFTS diff --git a/tokens/create-token/pinocchio/cicd.sh b/tokens/create-token/pinocchio/cicd.sh new file mode 100644 index 000000000..b2407c75f --- /dev/null +++ b/tokens/create-token/pinocchio/cicd.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# This script is for quick building & deploying of the program. +# It also serves as a reference for the commands used for building & deploying Solana programs. +# Run this bad boy with "bash cicd.sh" or "./cicd.sh" + +cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./program/target/so +solana program deploy ./program/target/so/program.so diff --git a/tokens/create-token/pinocchio/package.json b/tokens/create-token/pinocchio/package.json new file mode 100644 index 000000000..a00a1de30 --- /dev/null +++ b/tokens/create-token/pinocchio/package.json @@ -0,0 +1,24 @@ +{ + "type": "module", + "scripts": { + "postinstall": "node prepare.mjs", + "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/program.so" + }, + "dependencies": { + "@solana/web3.js": "^1.98.4", + "borsh": "^2.0.0" + }, + "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", + "solana-bankrun": "^0.3.0", + "ts-mocha": "^10.0.0", + "typescript": "^4.3.5" + } +} diff --git a/tokens/create-token/pinocchio/pnpm-lock.yaml b/tokens/create-token/pinocchio/pnpm-lock.yaml new file mode 100644 index 000000000..4b2f4d88c --- /dev/null +++ b/tokens/create-token/pinocchio/pnpm-lock.yaml @@ -0,0 +1,1357 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@solana/web3.js': + specifier: ^1.98.4 + version: 1.98.4(bufferutil@4.1.0)(typescript@4.9.5)(utf-8-validate@6.0.6) + borsh: + specifier: ^2.0.0 + version: 2.0.0 + devDependencies: + '@types/bn.js': + specifier: ^5.1.0 + version: 5.2.0 + '@types/chai': + specifier: ^4.3.1 + version: 4.3.20 + '@types/mocha': + specifier: ^9.1.1 + version: 9.1.1 + chai: + specifier: ^4.3.4 + version: 4.5.0 + mocha: + specifier: ^9.0.3 + version: 9.2.2 + solana-bankrun: + specifier: ^0.3.0 + version: 0.3.1(bufferutil@4.1.0)(typescript@4.9.5)(utf-8-validate@6.0.6) + ts-mocha: + specifier: ^10.0.0 + version: 10.1.0(mocha@9.2.2) + typescript: + specifier: ^4.3.5 + version: 4.9.5 + +packages: + + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + + '@noble/curves@1.9.7': + resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} + engines: {node: ^14.21.3 || >=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.21': + resolution: {integrity: sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==} + + '@types/bn.js@5.2.0': + resolution: {integrity: sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==} + + '@types/chai@4.3.20': + resolution: {integrity: sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==} + + '@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@25.9.1': + resolution: {integrity: sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==} + + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + + '@types/ws@7.4.7': + resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@ungap/promise-all-settled@1.1.2': + resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + 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.11: + resolution: {integrity: sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==} + + 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.3: + resolution: {integrity: sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==} + + borsh@0.7.0: + resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} + + borsh@2.0.0: + resolution: {integrity: sha512-kc9+BgR3zz9+cjbwM8ODoUB4fs3X3I5A/HtX7LZKxCLaMrEeDFoBpnhZY//DTS1VZBSs6S5v46RZRbZjRFspEg==} + + brace-expansion@1.1.14: + resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + 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@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bufferutil@4.1.0: + resolution: {integrity: sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==} + engines: {node: '>=6.14.2'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} + 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.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + 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==} + + 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.4: + resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} + engines: {node: '>=6'} + + delay@5.0.0: + resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} + engines: {node: '>=10'} + + diff@3.5.1: + resolution: {integrity: sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==} + 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.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + 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==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + 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==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + 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==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + 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.3.0: + resolution: {integrity: sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==} + 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 + + 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.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + 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.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + 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'} + + 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.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + 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'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + rpc-websockets@9.3.9: + resolution: {integrity: sha512-2iQDaTB4g5fDB2ihrTFSJSibCEuxaRi1q7qTW7ZO9/M5/TC+ToHA4D9/ffNLEbAoHNNrcdeP05oATNk44SKZXA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + serialize-javascript@6.0.0: + resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + + solana-bankrun-darwin-arm64@0.3.1: + resolution: {integrity: sha512-9LWtH/3/WR9fs8Ve/srdo41mpSqVHmRqDoo69Dv1Cupi+o1zMU6HiEPUHEvH2Tn/6TDbPEDf18MYNfReLUqE6A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + solana-bankrun-darwin-universal@0.3.1: + resolution: {integrity: sha512-muGHpVYWT7xCd8ZxEjs/bmsbMp8XBqroYGbE4lQPMDUuLvsJEIrjGqs3MbxEFr71sa58VpyvgywWd5ifI7sGIg==} + engines: {node: '>= 10'} + os: [darwin] + + solana-bankrun-darwin-x64@0.3.1: + resolution: {integrity: sha512-oCaxfHyt7RC3ZMldrh5AbKfy4EH3YRMl8h6fSlMZpxvjQx7nK7PxlRwMeflMnVdkKKp7U8WIDak1lilIPd3/lg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + solana-bankrun-linux-x64-gnu@0.3.1: + resolution: {integrity: sha512-PfRFhr7igGFNt2Ecfdzh3li9eFPB3Xhmk0Eib17EFIB62YgNUg3ItRnQQFaf0spazFjjJLnglY1TRKTuYlgSVA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + solana-bankrun-linux-x64-musl@0.3.1: + resolution: {integrity: sha512-6r8i0NuXg3CGURql8ISMIUqhE7Hx/O7MlIworK4oN08jYrP0CXdLeB/hywNn7Z8d1NXrox/NpYUgvRm2yIzAsQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + solana-bankrun@0.3.1: + resolution: {integrity: sha512-inRwON7fBU5lPC36HdEqPeDg15FXJYcf77+o0iz9amvkUMJepcwnRwEfTNyMVpVYdgjTOBW5vg+596/3fi1kGA==} + engines: {node: '>= 10'} + + 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'} + + stream-chain@2.2.5: + resolution: {integrity: sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==} + + stream-json@1.9.1: + resolution: {integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==} + + 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@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==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-mocha@10.1.0: + resolution: {integrity: sha512-T0C0Xm3/WqCuF2tpa0GNGESTBoKZaiqdUP8guNv4ZY316AFXlyidnrzQ1LUrCT0Wb1i3J0zFTgOh/55Un44WdA==} + 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 || ^11.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.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} + engines: {node: '>=4'} + + typescript@4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} + engines: {node: '>=4.2.0'} + hasBin: true + + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + + utf-8-validate@6.0.6: + resolution: {integrity: sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==} + engines: {node: '>=6.14.2'} + + uuid@14.0.0: + resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} + hasBin: true + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + 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.11: + resolution: {integrity: sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==} + 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.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} + 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: + + '@babel/runtime@7.29.7': {} + + '@noble/curves@1.9.7': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/hashes@1.8.0': {} + + '@solana/buffer-layout@4.0.1': + dependencies: + buffer: 6.0.3 + + '@solana/codecs-core@2.3.0(typescript@4.9.5)': + dependencies: + '@solana/errors': 2.3.0(typescript@4.9.5) + typescript: 4.9.5 + + '@solana/codecs-numbers@2.3.0(typescript@4.9.5)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@4.9.5) + '@solana/errors': 2.3.0(typescript@4.9.5) + typescript: 4.9.5 + + '@solana/errors@2.3.0(typescript@4.9.5)': + dependencies: + chalk: 5.6.2 + commander: 14.0.3 + typescript: 4.9.5 + + '@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@4.9.5)(utf-8-validate@6.0.6)': + dependencies: + '@babel/runtime': 7.29.7 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@solana/buffer-layout': 4.0.1 + '@solana/codecs-numbers': 2.3.0(typescript@4.9.5) + agentkeepalive: 4.6.0 + bn.js: 5.2.3 + borsh: 0.7.0 + bs58: 4.0.1 + buffer: 6.0.3 + fast-stable-stringify: 1.0.0 + jayson: 4.3.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + node-fetch: 2.7.0 + rpc-websockets: 9.3.9 + superstruct: 2.0.2 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + + '@swc/helpers@0.5.21': + dependencies: + tslib: 2.8.1 + + '@types/bn.js@5.2.0': + dependencies: + '@types/node': 25.9.1 + + '@types/chai@4.3.20': {} + + '@types/connect@3.4.38': + dependencies: + '@types/node': 12.20.55 + + '@types/json5@0.0.29': + optional: true + + '@types/mocha@9.1.1': {} + + '@types/node@12.20.55': {} + + '@types/node@25.9.1': + dependencies: + undici-types: 7.24.6 + + '@types/uuid@10.0.0': {} + + '@types/ws@7.4.7': + dependencies: + '@types/node': 12.20.55 + + '@types/ws@8.18.1': + dependencies: + '@types/node': 25.9.1 + + '@ungap/promise-all-settled@1.1.2': {} + + agentkeepalive@4.6.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.2 + + argparse@2.0.1: {} + + arrify@1.0.1: {} + + assertion-error@1.1.0: {} + + balanced-match@1.0.2: {} + + base-x@3.0.11: + dependencies: + safe-buffer: 5.2.1 + + base64-js@1.5.1: {} + + binary-extensions@2.3.0: {} + + bn.js@5.2.3: {} + + borsh@0.7.0: + dependencies: + bn.js: 5.2.3 + bs58: 4.0.1 + text-encoding-utf-8: 1.0.2 + + borsh@2.0.0: {} + + brace-expansion@1.1.14: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browser-stdout@1.3.1: {} + + bs58@4.0.1: + dependencies: + base-x: 3.0.11 + + buffer-from@1.1.2: {} + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bufferutil@4.1.0: + dependencies: + node-gyp-build: 4.8.4 + optional: true + + camelcase@6.3.0: {} + + chai@4.5.0: + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.4 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.1.0 + + 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.3 + 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.3: {} + + commander@2.20.3: {} + + concat-map@0.0.1: {} + + 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.4: + dependencies: + type-detect: 4.1.0 + + delay@5.0.0: {} + + diff@3.5.1: {} + + 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.2.0: {} + + escape-string-regexp@4.0.0: {} + + eventemitter3@5.0.4: {} + + eyes@0.1.8: {} + + fast-stable-stringify@1.0.0: {} + + fill-range@7.1.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.5 + 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.11(bufferutil@4.1.0)(utf-8-validate@6.0.6)): + dependencies: + ws: 7.5.11(bufferutil@4.1.0)(utf-8-validate@6.0.6) + + jayson@4.3.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): + dependencies: + '@types/connect': 3.4.38 + '@types/node': 12.20.55 + '@types/ws': 7.4.7 + 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.11(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + json-stringify-safe: 5.0.1 + stream-json: 1.9.1 + uuid: 8.3.2 + ws: 7.5.11(bufferutil@4.1.0)(utf-8-validate@6.0.6) + 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 + + 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.5: + dependencies: + brace-expansion: 1.1.14 + + minimatch@4.2.1: + dependencies: + brace-expansion: 1.1.14 + + 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.4: + 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 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + pathval@1.1.1: {} + + picomatch@2.3.2: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.2 + + require-directory@2.1.1: {} + + rpc-websockets@9.3.9: + dependencies: + '@swc/helpers': 0.5.21 + '@types/uuid': 10.0.0 + '@types/ws': 8.18.1 + buffer: 6.0.3 + eventemitter3: 5.0.4 + uuid: 14.0.0 + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + optionalDependencies: + bufferutil: 4.1.0 + utf-8-validate: 6.0.6 + + safe-buffer@5.2.1: {} + + serialize-javascript@6.0.0: + dependencies: + randombytes: 2.1.0 + + solana-bankrun-darwin-arm64@0.3.1: + optional: true + + solana-bankrun-darwin-universal@0.3.1: + optional: true + + solana-bankrun-darwin-x64@0.3.1: + optional: true + + solana-bankrun-linux-x64-gnu@0.3.1: + optional: true + + solana-bankrun-linux-x64-musl@0.3.1: + optional: true + + solana-bankrun@0.3.1(bufferutil@4.1.0)(typescript@4.9.5)(utf-8-validate@6.0.6): + dependencies: + '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@4.9.5)(utf-8-validate@6.0.6) + bs58: 4.0.1 + optionalDependencies: + solana-bankrun-darwin-arm64: 0.3.1 + solana-bankrun-darwin-universal: 0.3.1 + solana-bankrun-darwin-x64: 0.3.1 + solana-bankrun-linux-x64-gnu: 0.3.1 + solana-bankrun-linux-x64-musl: 0.3.1 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + stream-chain@2.2.5: {} + + stream-json@1.9.1: + dependencies: + stream-chain: 2.2.5 + + 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@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: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tr46@0.0.3: {} + + ts-mocha@10.1.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.1 + 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.8.1: {} + + type-detect@4.1.0: {} + + typescript@4.9.5: {} + + undici-types@7.24.6: {} + + utf-8-validate@6.0.6: + dependencies: + node-gyp-build: 4.8.4 + optional: true + + uuid@14.0.0: {} + + 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.11(bufferutil@4.1.0)(utf-8-validate@6.0.6): + optionalDependencies: + bufferutil: 4.1.0 + utf-8-validate: 6.0.6 + + ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): + optionalDependencies: + bufferutil: 4.1.0 + utf-8-validate: 6.0.6 + + 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.2.0 + 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/tokens/create-token/pinocchio/prepare.mjs b/tokens/create-token/pinocchio/prepare.mjs new file mode 100644 index 000000000..920f1ccbf --- /dev/null +++ b/tokens/create-token/pinocchio/prepare.mjs @@ -0,0 +1,35 @@ +// Dumps the Metaplex Token Metadata program from mainnet into the bankrun +// fixtures directory so the test can load it into the local test validator. +// Runs automatically via the `postinstall` script. +// +// Uses only the Node.js standard library (no extra dependencies). Errors are +// logged but not fatal — a missing fixture will surface as a clear test failure +// when bankrun can't find `token_metadata.so`. + +import { execSync } from "node:child_process"; +import { mkdirSync, rmSync } from "node:fs"; +import { join } from "node:path"; + +const programs = [ + { + id: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", + name: "token_metadata.so", + }, +]; + +const outputDir = "tests/fixtures"; + +try { + mkdirSync(outputDir, { recursive: true }); + + for (const { id, name } of programs) { + const outputFile = join(outputDir, name); + rmSync(outputFile, { force: true }); + // `-um` fetches from mainnet (where the canonical program lives) without + // touching the user's Solana CLI config. + execSync(`solana program dump -um ${id} ${outputFile}`, { stdio: "inherit" }); + console.log(`Dumped ${id} -> ${outputFile}`); + } +} catch (error) { + console.error(`Failed to prepare program fixtures: ${error.message}`); +} diff --git a/tokens/create-token/pinocchio/program/Cargo.toml b/tokens/create-token/pinocchio/program/Cargo.toml new file mode 100644 index 000000000..f601b719d --- /dev/null +++ b/tokens/create-token/pinocchio/program/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "create-token-pinocchio-program" +version = "0.1.0" +edition = "2021" + +[dependencies] +pinocchio.workspace = true +pinocchio-log.workspace = true +pinocchio-system.workspace = true +pinocchio-token.workspace = true + +[lib] +crate-type = ["cdylib", "lib"] + +[features] +custom-heap = [] +custom-panic = [] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/tokens/create-token/pinocchio/program/src/instructions/create_token.rs b/tokens/create-token/pinocchio/program/src/instructions/create_token.rs new file mode 100644 index 000000000..c69c9b806 --- /dev/null +++ b/tokens/create-token/pinocchio/program/src/instructions/create_token.rs @@ -0,0 +1,176 @@ +use pinocchio::{ + cpi::invoke, + error::ProgramError, + instruction::{InstructionAccount, InstructionView}, + sysvars::rent::{ACCOUNT_STORAGE_OVERHEAD, DEFAULT_LAMPORTS_PER_BYTE}, + AccountView, ProgramResult, +}; +use pinocchio_log::log; +use pinocchio_system::instructions::CreateAccount; +use pinocchio_token::{instructions::InitializeMint2, state::Mint}; + +use crate::instructions::util::{read_borsh_string, write_borsh_string, write_bytes}; + +/// The Metaplex Token Metadata program ID +/// (`metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s`). +const TOKEN_METADATA_PROGRAM_ID: pinocchio::Address = + pinocchio::Address::from_str_const("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); + +/// Discriminator of the Metaplex `CreateMetadataAccountV3` instruction (variant +/// 33 of the Token Metadata program's instruction enum). +const CREATE_METADATA_ACCOUNT_V3: u8 = 33; + +/// Upper bound on the serialized `CreateMetadataAccountV3` data, using the +/// Metaplex field maxima (name ≤ 32, symbol ≤ 10, uri ≤ 200). Sizing a fixed +/// stack buffer keeps the program `alloc`-free. +const METADATA_DATA_MAX: usize = 1 // discriminator + + 4 + 32 // name + + 4 + 10 // symbol + + 4 + 200 // uri + + 2 // seller_fee_basis_points + + 3 // creators / collection / uses (all None) + + 1 // is_mutable + + 1; // collection_details (None) + +/// Borsh-encoded arguments for the create-token instruction. +/// +/// Field order matches the `native` example's `CreateTokenArgs` so the two +/// options share an identical wire format. +pub struct CreateTokenArgs<'a> { + pub name: &'a [u8], + pub symbol: &'a [u8], + pub uri: &'a [u8], + pub decimals: u8, +} + +impl<'a> CreateTokenArgs<'a> { + /// Parses the instruction data: three Borsh strings followed by a `u8`. + pub fn parse(data: &'a [u8]) -> Result { + let mut offset = 0; + let name = read_borsh_string(data, &mut offset)?; + let symbol = read_borsh_string(data, &mut offset)?; + let uri = read_borsh_string(data, &mut offset)?; + let decimals = *data + .get(offset) + .ok_or(ProgramError::InvalidInstructionData)?; + Ok(Self { + name, + symbol, + uri, + decimals, + }) + } +} + +/// Creates a new SPL Token mint and attaches an on-chain Metaplex metadata +/// account to it (name, symbol, URI). +/// +/// Accounts: +/// 0. `[signer, writable]` mint account (a fresh keypair to initialize) +/// 1. `[]` mint authority (also recorded as metadata update authority) +/// 2. `[writable]` metadata account (the Metaplex metadata PDA) +/// 3. `[signer, writable]` payer (funds the new accounts) +/// 4. `[]` system program +/// 5. `[]` token program +/// 6. `[]` token metadata program +/// +/// Instruction data: Borsh `[name: string, symbol: string, uri: string, decimals: u8]`. +/// +/// The mint authority is passed as a non-signer; the metadata CPI requires it to +/// sign, which is satisfied by passing the payer's address for it (the payer +/// signs the transaction). This mirrors the `native` example. +pub fn create_token(accounts: &[AccountView], data: &[u8]) -> ProgramResult { + // `token_program` and `token_metadata_program` are unused directly, but must + // be supplied so they are present in the transaction for the CPIs below. + let [mint_account, mint_authority, metadata_account, payer, system_program, _token_program, _token_metadata_program] = + accounts + else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + let args = CreateTokenArgs::parse(data)?; + + // Rent-exempt minimum for the mint, computed with integer math using the + // network's default rent parameters (`DEFAULT_LAMPORTS_PER_BYTE` already + // folds in the 2-year exemption threshold). We avoid + // `Rent::try_minimum_balance`, whose floating-point exemption-threshold path + // emits an instruction the bankrun test VM rejects ("unsupported BPF + // instruction"). + let lamports = (ACCOUNT_STORAGE_OVERHEAD + Mint::LEN as u64) * DEFAULT_LAMPORTS_PER_BYTE; + + log!("Creating mint account"); + CreateAccount { + from: payer, + to: mint_account, + lamports, + space: Mint::LEN as u64, + owner: &pinocchio_token::ID, + } + .invoke()?; + + log!("Initializing mint account"); + InitializeMint2 { + mint: mint_account, + decimals: args.decimals, + mint_authority: mint_authority.address(), + freeze_authority: Some(mint_authority.address()), + } + .invoke()?; + + log!("Creating metadata account"); + let mut metadata_buffer = [0u8; METADATA_DATA_MAX]; + let metadata_len = build_metadata_data(&args, &mut metadata_buffer)?; + let metadata_data = &metadata_buffer[..metadata_len]; + let metadata_accounts = [ + InstructionAccount::writable(metadata_account.address()), + InstructionAccount::readonly(mint_account.address()), + InstructionAccount::readonly_signer(mint_authority.address()), + InstructionAccount::writable_signer(payer.address()), + // Update authority — recorded only, not required to sign for V3. + InstructionAccount::readonly(mint_authority.address()), + InstructionAccount::readonly(system_program.address()), + ]; + let instruction = InstructionView { + program_id: &TOKEN_METADATA_PROGRAM_ID, + accounts: &metadata_accounts, + data: metadata_data, + }; + invoke( + &instruction, + &[ + metadata_account, + mint_account, + mint_authority, + payer, + mint_authority, + system_program, + ], + )?; + + log!("Token mint created successfully"); + Ok(()) +} + +/// Serializes the data for a Metaplex `CreateMetadataAccountV3` instruction into +/// `buffer`, returning the number of bytes written. +/// +/// Layout: `[33] DataV2 is_mutable:bool collection_details:Option`, where +/// `DataV2` is `name:string symbol:string uri:string seller_fee:u16 +/// creators:Option collection:Option uses:Option`. Mirrors the values used by +/// the `anchor` and `native` examples (no royalties, no creators, immutable). +fn build_metadata_data(args: &CreateTokenArgs, buffer: &mut [u8]) -> Result { + let mut offset = 0; + write_bytes(buffer, &mut offset, &[CREATE_METADATA_ACCOUNT_V3])?; + + // DataV2 + write_borsh_string(buffer, &mut offset, args.name)?; + write_borsh_string(buffer, &mut offset, args.symbol)?; + write_borsh_string(buffer, &mut offset, args.uri)?; + write_bytes(buffer, &mut offset, &0u16.to_le_bytes())?; // seller_fee_basis_points + write_bytes(buffer, &mut offset, &[0, 0, 0])?; // creators / collection / uses: None + + write_bytes(buffer, &mut offset, &[0])?; // is_mutable: false + write_bytes(buffer, &mut offset, &[0])?; // collection_details: None + + Ok(offset) +} diff --git a/tokens/create-token/pinocchio/program/src/instructions/mod.rs b/tokens/create-token/pinocchio/program/src/instructions/mod.rs new file mode 100644 index 000000000..1741d32c8 --- /dev/null +++ b/tokens/create-token/pinocchio/program/src/instructions/mod.rs @@ -0,0 +1,4 @@ +mod create_token; +mod util; + +pub use create_token::*; diff --git a/tokens/create-token/pinocchio/program/src/instructions/util.rs b/tokens/create-token/pinocchio/program/src/instructions/util.rs new file mode 100644 index 000000000..93af6ceb6 --- /dev/null +++ b/tokens/create-token/pinocchio/program/src/instructions/util.rs @@ -0,0 +1,46 @@ +use pinocchio::error::ProgramError; + +/// Reads a Borsh `string` (a 4-byte little-endian length prefix followed by that +/// many UTF-8 bytes) starting at `*offset`, advancing `offset` past it. +pub fn read_borsh_string<'a>(data: &'a [u8], offset: &mut usize) -> Result<&'a [u8], ProgramError> { + let len_bytes: [u8; 4] = data + .get(*offset..*offset + 4) + .ok_or(ProgramError::InvalidInstructionData)? + .try_into() + .map_err(|_| ProgramError::InvalidInstructionData)?; + let len = u32::from_le_bytes(len_bytes) as usize; + *offset += 4; + + let bytes = data + .get(*offset..*offset + len) + .ok_or(ProgramError::InvalidInstructionData)?; + *offset += len; + Ok(bytes) +} + +/// Writes `bytes` into `buffer` at `*offset`, advancing `offset`. Returns +/// `InvalidInstructionData` if they don't fit — keeping the program `alloc`-free +/// (a growable `Vec` pulls in codegen the bankrun test runtime can't execute). +pub fn write_bytes( + buffer: &mut [u8], + offset: &mut usize, + bytes: &[u8], +) -> Result<(), ProgramError> { + let end = *offset + bytes.len(); + buffer + .get_mut(*offset..end) + .ok_or(ProgramError::InvalidInstructionData)? + .copy_from_slice(bytes); + *offset = end; + Ok(()) +} + +/// Writes a Borsh `string` (4-byte little-endian length prefix + UTF-8 bytes). +pub fn write_borsh_string( + buffer: &mut [u8], + offset: &mut usize, + value: &[u8], +) -> Result<(), ProgramError> { + write_bytes(buffer, offset, &(value.len() as u32).to_le_bytes())?; + write_bytes(buffer, offset, value) +} diff --git a/tokens/create-token/pinocchio/program/src/lib.rs b/tokens/create-token/pinocchio/program/src/lib.rs new file mode 100644 index 000000000..a8cd1e13d --- /dev/null +++ b/tokens/create-token/pinocchio/program/src/lib.rs @@ -0,0 +1,13 @@ +#![no_std] + +pub mod instructions; +pub mod processor; + +use pinocchio::{no_allocator, nostd_panic_handler, program_entrypoint}; + +program_entrypoint!(processor::process_instruction); +// The program builds its instruction data in fixed stack buffers, so no heap +// allocator is needed. `entrypoint!`'s default bump allocator pulls in codegen +// the bankrun test runtime rejects ("unsupported BPF instruction"). +no_allocator!(); +nostd_panic_handler!(); diff --git a/tokens/create-token/pinocchio/program/src/processor.rs b/tokens/create-token/pinocchio/program/src/processor.rs new file mode 100644 index 000000000..c34269c15 --- /dev/null +++ b/tokens/create-token/pinocchio/program/src/processor.rs @@ -0,0 +1,21 @@ +use pinocchio::{AccountView, Address, ProgramResult}; +use pinocchio_log::log; + +use crate::instructions::create_token; + +/// Entrypoint for the program. +/// +/// This example exposes a single instruction (creating a token), so — unlike +/// the `transfer-tokens` and `escrow` examples — there is no leading +/// discriminator byte. The whole instruction data is the Borsh-encoded +/// `CreateTokenArgs`, matching the wire format of the `native` version: +/// +/// `[name: string, symbol: string, uri: string, decimals: u8]` +pub fn process_instruction( + _program_id: &Address, + accounts: &[AccountView], + instruction_data: &[u8], +) -> ProgramResult { + log!("Instruction: CreateToken"); + create_token(accounts, instruction_data) +} diff --git a/tokens/create-token/pinocchio/tests/test.ts b/tokens/create-token/pinocchio/tests/test.ts new file mode 100644 index 000000000..dfd437a50 --- /dev/null +++ b/tokens/create-token/pinocchio/tests/test.ts @@ -0,0 +1,125 @@ +import { Buffer } from "node:buffer"; +import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js"; +import * as borsh from "borsh"; +import { assert } from "chai"; +import { start } from "solana-bankrun"; + +// The legacy SPL Token program is bundled with bankrun. The Metaplex Token +// Metadata program is not, so it is dumped from mainnet into tests/fixtures by +// prepare.mjs and loaded by name below. +const TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); +const TOKEN_METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); + +// Borsh schema for the instruction data, matching the program's `CreateTokenArgs` +// (and the native example's wire format). +const CreateTokenArgsSchema: borsh.Schema = { + struct: { + token_title: "string", + token_symbol: "string", + token_uri: "string", + token_decimals: "u8", + }, +}; + +// Derive the Metaplex metadata PDA for a mint. +function getMetadataAddress(mint: PublicKey): PublicKey { + return PublicKey.findProgramAddressSync( + [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], + TOKEN_METADATA_PROGRAM_ID, + )[0]; +} + +describe("Create Token (Pinocchio)", () => { + const PROGRAM_ID = PublicKey.unique(); + let context: Awaited>; + let client: (typeof context)["banksClient"]; + let payer: (typeof context)["payer"]; + + // A `describe` callback runs synchronously, so the async bankrun setup must + // live in a `before` hook — otherwise the `it` blocks register after Mocha + // has already collected the suite and nothing runs. + before(async () => { + context = await start( + [ + { name: "create_token_pinocchio_program", programId: PROGRAM_ID }, + { name: "token_metadata", programId: TOKEN_METADATA_PROGRAM_ID }, + ], + [], + ); + client = context.banksClient; + payer = context.payer; + }); + + async function createToken(name: string, symbol: string, uri: string, decimals: number) { + const mintKeypair = Keypair.generate(); + const metadataAddress = getMetadataAddress(mintKeypair.publicKey); + + const data = Buffer.from( + borsh.serialize(CreateTokenArgsSchema, { + token_title: name, + token_symbol: symbol, + token_uri: uri, + token_decimals: decimals, + }), + ); + + const ix = new TransactionInstruction({ + programId: PROGRAM_ID, + keys: [ + { pubkey: mintKeypair.publicKey, isSigner: true, isWritable: true }, // mint account + { pubkey: payer.publicKey, isSigner: false, isWritable: false }, // mint authority + { pubkey: metadataAddress, isSigner: false, isWritable: true }, // metadata account + { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // payer + { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // system program + { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // token program + { pubkey: TOKEN_METADATA_PROGRAM_ID, isSigner: false, isWritable: false }, // token metadata program + ], + data, + }); + + const tx = new Transaction(); + tx.feePayer = payer.publicKey; + tx.recentBlockhash = context.lastBlockhash; + tx.add(ix); + tx.sign(payer, mintKeypair); + await client.processTransaction(tx); + + return { mint: mintKeypair.publicKey, metadata: metadataAddress }; + } + + it("Create an SPL Token!", async () => { + const { mint, metadata } = await createToken( + "Solana Gold", + "GOLDSOL", + "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json", + 9, + ); + + const mintAccount = await client.getAccount(mint); + if (mintAccount === null) throw new Error("Mint account not found"); + assert.deepEqual(mintAccount.owner.toBytes(), TOKEN_PROGRAM_ID.toBytes()); + + const metadataAccount = await client.getAccount(metadata); + if (metadataAccount === null) throw new Error("Metadata account not found"); + assert.deepEqual(metadataAccount.owner.toBytes(), TOKEN_METADATA_PROGRAM_ID.toBytes()); + assert.isTrue(Buffer.from(metadataAccount.data).toString("utf-8").includes("Solana Gold")); + }); + + it("Create an NFT!", async () => { + const { mint, metadata } = await createToken( + "Homer NFT", + "HOMR", + "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json", + 0, + ); + + const mintAccount = await client.getAccount(mint); + if (mintAccount === null) throw new Error("Mint account not found"); + assert.deepEqual(mintAccount.owner.toBytes(), TOKEN_PROGRAM_ID.toBytes()); + + const metadataAccount = await client.getAccount(metadata); + if (metadataAccount === null) throw new Error("Metadata account not found"); + assert.deepEqual(metadataAccount.owner.toBytes(), TOKEN_METADATA_PROGRAM_ID.toBytes()); + assert.isTrue(Buffer.from(metadataAccount.data).toString("utf-8").includes("Homer NFT")); + }); +}); diff --git a/tokens/create-token/pinocchio/tsconfig.json b/tokens/create-token/pinocchio/tsconfig.json new file mode 100644 index 000000000..8c20b2236 --- /dev/null +++ b/tokens/create-token/pinocchio/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "types": ["mocha", "chai", "node"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "commonjs", + "target": "es6", + "esModuleInterop": true + } +}