diff --git a/basics/anchorpy-main/Makefile b/basics/anchorpy-main/Makefile
new file mode 100644
index 0000000..b334067
--- /dev/null
+++ b/basics/anchorpy-main/Makefile
@@ -0,0 +1,12 @@
+test:
+ poetry run pytest -vv
+
+init-clientgen-examples:
+ cd tests/client_gen/example-program/ && anchor idl parse -f programs/example-program/src/lib.rs -o ../../idls/clientgen_example_program.json && cd ../../.. && poetry run anchorpy client-gen tests/idls/clientgen_example_program.json tests/client_gen/example_program_gen --program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 --pdas
+ poetry run anchorpy client-gen tests/idls/basic_2.json examples/client-gen/basic_2 --program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8
+ poetry run anchorpy client-gen tests/idls/tictactoe.json examples/client-gen/tictactoe --program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8
+ poetry run anchorpy client-gen tests/idls/spl_token.json tests/client_gen/token --program-id TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
+
+lint:
+ poetry run ruff src tests
+ poetry run mypy src tests
diff --git a/basics/anchorpy-main/README.md b/basics/anchorpy-main/README.md
new file mode 100644
index 0000000..aceffbb
--- /dev/null
+++ b/basics/anchorpy-main/README.md
@@ -0,0 +1,38 @@
+# AnchorPy
+
+
+AnchorPy is the gateway to interacting with [Anchor](https://github.com/project-serum/anchor) programs in Python.
+It provides:
+
+- A static client generator
+- A dynamic client similar to `anchor-ts`
+- A Pytest plugin
+- A CLI with various utilities for Anchor Python development.
+
+
+
+
+## Installation (requires Python >=3.9)
+
+```sh
+pip install anchorpy[cli]
+
+```
+Or, if you're not using the CLI features of AnchorPy you can just run `pip install anchorpy`.
+
+### Development Setup
+
+If you want to contribute to AnchorPy, follow these steps to get set up:
+
+1. Install [poetry](https://python-poetry.org/docs/#installation)
+2. Install dev dependencies:
+```sh
+poetry install
+
+```
+3. Install [nox-poetry](https://github.com/cjolowicz/nox-poetry) (note: do not use Poetry to install this, see [here](https://medium.com/@cjolowicz/nox-is-a-part-of-your-global-developer-environment-like-poetry-pre-commit-pyenv-or-pipx-1cdeba9198bd))
+4. Activate the poetry shell:
+```sh
+poetry shell
+
+```
diff --git a/basics/anchorpy-main/docs/cli/index.md b/basics/anchorpy-main/docs/cli/index.md
new file mode 100644
index 0000000..d32f867
--- /dev/null
+++ b/basics/anchorpy-main/docs/cli/index.md
@@ -0,0 +1,80 @@
+# AnchorPy CLI
+
+AnchorPy comes with a CLI to make your life easier when using Python with Anchor.
+
+
+```console
+$ anchorpy --help
+Usage: anchorpy [OPTIONS] COMMAND [ARGS]...
+
+ AnchorPy CLI.
+
+Options:
+ --install-completion [bash|zsh|fish|powershell|pwsh]
+ Install completion for the specified shell.
+ --show-completion [bash|zsh|fish|powershell|pwsh]
+ Show completion for the specified shell, to
+ copy it or customize the installation.
+ --help Show this message and exit.
+
+Commands:
+ init Create a basic Python test file for an Anchor program.
+ shell Start IPython shell with AnchorPy workspace object initialized.
+```
+
+## Commands
+
+### Init
+
+```console
+$ anchorpy init --help
+Usage: anchorpy init [OPTIONS] PROGRAM_NAME
+
+ Create a basic Python test file for an Anchor program.
+
+ This does not replace `anchor init`, but rather should be run after it.
+
+ The test file will live at `tests/test_$PROGRAM_NAME.py`.
+
+Arguments:
+ PROGRAM_NAME The name of the Anchor program. [required]
+
+Options:
+ --help Show this message and exit.
+```
+
+### Shell
+
+```console
+$ anchorpy shell --help
+Usage: anchorpy shell [OPTIONS]
+
+ Start IPython shell with AnchorPy workspace object initialized.
+
+ Note that you should run `anchor localnet` before `anchorpy shell`.
+
+Options:
+ --help Show this message and exit.
+```
+
+#### Example
+
+
+
+```console
+$ cd anchor/examples/tutorial/basic-0 && anchorpy shell
+Python 3.9.1 (default, Dec 11 2020, 14:32:07)
+Type 'copyright', 'credits' or 'license' for more information
+IPython 7.30.1 -- An enhanced Interactive Python. Type '?' for help.
+
+Hint: type `workspace` to see the Anchor workspace object.
+
+# In [1]:$ await workspace["basic_0"].rpc["initialize"]()
+Out[1]: '2q1Z8BcsSBikMLEFoeFGhUukfsNYLJx7y33rMZ57Eh4gAHJxpJ9oP9b9aFyrizh9wcuiVtAAxvmBifCXdqWeNLor'
+```
+
+
+
+### Client-gen
+
+See [Client Generator](../clientgen)
\ No newline at end of file
diff --git a/basics/anchorpy-main/docs/clientgen/index.md b/basics/anchorpy-main/docs/clientgen/index.md
new file mode 100644
index 0000000..d44f8ce
--- /dev/null
+++ b/basics/anchorpy-main/docs/clientgen/index.md
@@ -0,0 +1,206 @@
+# Client Generator
+
+The `anchorpy client-gen` command generates a Python client based on an Anchor IDL. This client provides functions for
+generating instructions and class definitions for fetching and serializing accounts. The output is very similar
+to the Typescript code produced by [anchor-client-gen](https://github.com/kklas/anchor-client-gen).
+
+## Features
+
+- Fully typed.
+- Supports all Anchor field types.
+- Makes enums and complex types easy to work with.
+- Generates error classes for each error.
+- Provides `to_json` and `from_json` utility functions for types and accounts.
+
+!!! note
+ It is recommended to use the generated client instead of the dynamic client where possible, as it is easier to
+ work with and comes with proper type hints.
+
+## Usage
+
+```console
+$ anchorpy client-gen --help
+Usage: anchorpy client-gen [OPTIONS] IDL OUT
+
+ Generate Python client code from the specified anchor IDL.
+
+Arguments:
+ IDL Anchor IDL file path [required]
+ OUT Output directory. [required]
+
+Options:
+ --program-id TEXT Optional program ID to be included in the code
+ --help Show this message and exit.
+
+```
+
+## Example
+
+
+
+```console
+$ anchorpy client-gen path/to/idl.json ./my_client
+generating package...
+generating program_id.py...
+generating errors.py...
+generating instructions...
+generating types...
+generating accounts...
+```
+
+
+
+This will generate code to `./my_client`:
+
+```
+.
+├── accounts
+│ ├── foo_account.py
+│ └── __init__.py
+├── instructions
+│ ├── some_instruction.py
+│ ├── other_instruction.py
+│ └── __init__.py
+├── types
+│ ├── bar_struct.py
+│ ├── baz_enum.py
+│ └── __init__.py
+├── errors
+│ ├── anchor.py
+│ ├── custom.py
+│ └── __init__.py
+└── program_id.py
+```
+
+## Using the generated client
+
+### Instructions
+
+```python
+from solana.transaction import Transaction
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+from anchorpy import Provider
+from my_client.instructions import some_instruction
+
+ # call an instruction
+foo_account = Keypair()
+
+ix = some_instruction({
+ "foo_param": "...",
+ "bar_param": "...",
+ ...
+}, {
+ "foo_account": foo_account.pubkey(), # signer
+ "bar_account": Pubkey("..."),
+ ...
+})
+tx = Transaction().add(ix)
+
+provider = Provider.local()
+
+await provider.send(tx, [payer, foo_account])
+```
+
+### Accounts
+
+```python
+from solders.pubkey import Pubkey
+from my_client.accounts import FooAccount
+
+# fetch an account
+addr = Pubkey("...")
+
+acc = await FooAccount.fetch(connection, addr)
+if acc is None:
+ # the fetch method returns null when the account is uninitialized
+ raise ValueError("account not found")
+
+
+# convert to a JSON object
+obj = acc.to_json()
+print(obj)
+
+# load from JSON
+acc_from_json = FooAccount.from_json(obj)
+```
+
+### Types
+
+```python
+# structs
+
+from my_client.types import BarStruct
+
+bar_struct = BarStruct(
+ some_field="...",
+ other_field="...",
+)
+
+print(bar_struct.to_json())
+```
+
+```python
+# enums
+
+from my_client.types import baz_enum
+
+tuple_enum = baz_enum.SomeTupleKind((True, False, "some value"))
+struct_enum = baz_enum.SomeStructKind({
+ "field1": "...",
+ "field2": "...",
+})
+disc_enum = baz_enum.SomeDiscriminantKind()
+
+print(tuple_enum.toJSON(), struct_enum.toJSON(), disc_enum.toJSON())
+```
+
+```python
+# types are used as arguments in instruction calls (where needed):
+ix = some_instruction({
+ "some_struct_field": bar_struct,
+ "some_enum_field": tuple_enum,
+ # ...
+}, {
+ # accounts
+ # ...
+})
+
+# in case of struct fields, it's also possible to pass them as objects:
+ix = some_instruction({
+ "some_struct_field": {
+ "some_field": "...",
+ "other_field": "...",
+ },
+ # ...,
+}, {
+ # accounts
+ # ...
+})
+```
+
+### Errors
+
+```python
+from solana.rpc.core import RPCException
+from my_client.errors import from_tx_error
+from my_client.errors.custom import SomeCustomError
+
+try:
+ await provider.send(tx, [payer])
+except RPCException as exc:
+ parsed = from_tx_error(exc)
+ raise parsed from exc
+```
+
+## Program ID
+
+The client generator pulls the program ID from:
+
+- the input IDL
+- the `--program-id` flag
+
+If the IDL doesn't contain the program ID then you will need to pass it via the `--program-id` flag.
+
+This program ID is then written into the `program_id.py` file.
+
diff --git a/basics/anchorpy-main/docs/css/custom.css b/basics/anchorpy-main/docs/css/custom.css
new file mode 100644
index 0000000..574fc63
--- /dev/null
+++ b/basics/anchorpy-main/docs/css/custom.css
@@ -0,0 +1,25 @@
+.termynal-comment {
+ color: #4a968f;
+ font-style: italic;
+ display: block;
+}
+
+.termy [data-termynal] {
+ white-space: pre-wrap;
+ font-size: 14px;
+ overflow-wrap: break-word;
+}
+
+a.external-link::after {
+ /* \00A0 is a non-breaking space
+ to make the mark be on the same line as the link
+ */
+ content: "\00A0[↪]";
+}
+
+a.internal-link::after {
+ /* \00A0 is a non-breaking space
+ to make the mark be on the same line as the link
+ */
+ content: "\00A0↪";
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/docs/css/mkdocstrings.css b/basics/anchorpy-main/docs/css/mkdocstrings.css
new file mode 100644
index 0000000..024fe6e
--- /dev/null
+++ b/basics/anchorpy-main/docs/css/mkdocstrings.css
@@ -0,0 +1,6 @@
+/* Indentation. */
+div.doc-contents:not(.first) {
+ padding-left: 25px;
+ border-left: 4px solid rgba(230, 230, 230);
+ margin-bottom: 80px;
+ }
diff --git a/basics/anchorpy-main/docs/css/termynal.css b/basics/anchorpy-main/docs/css/termynal.css
new file mode 100644
index 0000000..dfe3caa
--- /dev/null
+++ b/basics/anchorpy-main/docs/css/termynal.css
@@ -0,0 +1,108 @@
+/**
+ * termynal.js
+ *
+ * @author Ines Montani
+ * @version 0.0.1
+ * @license MIT
+ */
+
+ :root {
+ --color-bg: #252a33;
+ --color-text: #eee;
+ --color-text-subtle: #a2a2a2;
+}
+
+[data-termynal] {
+ width: 750px;
+ max-width: 100%;
+ background: var(--color-bg);
+ color: var(--color-text);
+ font-size: 18px;
+ /* font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; */
+ font-family: 'Roboto Mono', 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace;
+ border-radius: 4px;
+ padding: 75px 45px 35px;
+ position: relative;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+[data-termynal]:before {
+ content: '';
+ position: absolute;
+ top: 15px;
+ left: 15px;
+ display: inline-block;
+ width: 15px;
+ height: 15px;
+ border-radius: 50%;
+ /* A little hack to display the window buttons in one pseudo element. */
+ background: #d9515d;
+ -webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;
+ box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;
+}
+
+[data-termynal]:after {
+ content: 'bash';
+ position: absolute;
+ color: var(--color-text-subtle);
+ top: 5px;
+ left: 0;
+ width: 100%;
+ text-align: center;
+}
+
+a[data-terminal-control] {
+ text-align: right;
+ display: block;
+ color: #aebbff;
+}
+
+[data-ty] {
+ display: block;
+ line-height: 2;
+}
+
+[data-ty]:before {
+ /* Set up defaults and ensure empty lines are displayed. */
+ content: '';
+ display: inline-block;
+ vertical-align: middle;
+}
+
+[data-ty="input"]:before,
+[data-ty-prompt]:before {
+ margin-right: 0.75em;
+ color: var(--color-text-subtle);
+}
+
+[data-ty="input"]:before {
+ content: '$';
+}
+
+[data-ty][data-ty-prompt]:before {
+ content: attr(data-ty-prompt);
+}
+
+[data-ty-cursor]:after {
+ content: attr(data-ty-cursor);
+ font-family: monospace;
+ margin-left: 0.5em;
+ -webkit-animation: blink 1s infinite;
+ animation: blink 1s infinite;
+}
+
+
+/* Cursor animation */
+
+@-webkit-keyframes blink {
+ 50% {
+ opacity: 0;
+ }
+}
+
+@keyframes blink {
+ 50% {
+ opacity: 0;
+ }
+}
diff --git a/basics/anchorpy-main/docs/dynamic_client/api_reference.md b/basics/anchorpy-main/docs/dynamic_client/api_reference.md
new file mode 100644
index 0000000..261b98d
--- /dev/null
+++ b/basics/anchorpy-main/docs/dynamic_client/api_reference.md
@@ -0,0 +1,27 @@
+# API Reference
+
+
+:::anchorpy.Program
+:::anchorpy.Provider
+:::anchorpy.Context
+:::anchorpy.create_workspace
+:::anchorpy.close_workspace
+:::anchorpy.bankrun_fixture
+:::anchorpy.workspace_fixture
+:::anchorpy.localnet_fixture
+:::anchorpy.Wallet
+:::anchorpy.Coder
+:::anchorpy.InstructionCoder
+:::anchorpy.EventCoder
+:::anchorpy.AccountsCoder
+:::anchorpy.NamedInstruction
+:::anchorpy.IdlProgramAccount
+:::anchorpy.Event
+:::anchorpy.translate_address
+:::anchorpy.validate_accounts
+:::anchorpy.AccountClient
+:::anchorpy.ProgramAccount
+:::anchorpy.EventParser
+:::anchorpy.SimulateResponse
+:::anchorpy.error
+:::anchorpy.utils
diff --git a/basics/anchorpy-main/docs/dynamic_client/comparison_with_anchor_ts.md b/basics/anchorpy-main/docs/dynamic_client/comparison_with_anchor_ts.md
new file mode 100644
index 0000000..db3e220
--- /dev/null
+++ b/basics/anchorpy-main/docs/dynamic_client/comparison_with_anchor_ts.md
@@ -0,0 +1,36 @@
+# Comparison with Typescript
+
+While AnchorPy is quite similar to the Anchor Typescript client,
+there are some differences:
+
+## Dictionaries instead of objects
+
+AnchorPy tends to use dictionaries, so it uses `[key]` in some places where
+`anchor-ts` would use `.key`.
+For example, AnchorPy uses `workspace["basic_1"]` instead of `workspace.basic_1`,
+and `program.rpc["initialize"]()` instead of `program.rpc.initialize()`
+
+## Explicit `Context` object
+
+AnchorPy uses a `Context` dataclass and has a `ctx` keyword argument when
+calling `.rpc` functions, whereas Typescript is a bit less structured.
+
+We call `program.rpc["my_func"](ctx=Context({"my_account": my_account}))`
+instead of `program.rpc["my_func"]({"my_account": my_account})`
+
+## snake_case 🐍 instead of camelCase 🐪
+
+AnchorPy uses more `snake_case` to match Rust and be Pythonic.
+Specifically, the following names are snake-case in AnchorPy:
+
+- Workspaces: `workspace["puppet_master"]` instead of `workspace["puppetMaster"]`
+- Instructions: `program.rpc["my_func"]` (and `program.instruction["my_func"]`) instead of
+`program.rpc["myFunc"]`.
+- Accounts in the `ctx` arg: `{"my_account": my_account}` instead of `{"myAccount": my_account}`
+- Fields in user-defined types: `program.type["TransactionAccount"](is_writable=True)` instead of
+`program.type["TransactionAccount"](isWritable=True)`
+
+## `program.type` namespace for user-defined types
+
+The AnchorPy `Program` object has a `.type` attribute for instantiating user-defined types. This is not present in
+the Typescript client. See the [examples](examples.md) for more on this.
diff --git a/basics/anchorpy-main/docs/dynamic_client/examples.md b/basics/anchorpy-main/docs/dynamic_client/examples.md
new file mode 100644
index 0000000..b91b806
--- /dev/null
+++ b/basics/anchorpy-main/docs/dynamic_client/examples.md
@@ -0,0 +1,85 @@
+# Examples
+
+Here are some of the other things you can do with AnchorPy:
+
+## Loading a Program from an on-chain IDL
+
+If a program's IDL is stored on-chain, you can use it
+to initialize a program object using `Program.at`.
+
+````python
+import asyncio
+from solana.rpc.async_api import AsyncClient
+from solders.pubkey import Pubkey
+from anchorpy import Program, Provider, Wallet
+
+
+async def main():
+ client = AsyncClient("https://api.mainnet-beta.solana.com/")
+ provider = Provider(client, Wallet.local())
+ # load the Serum Swap Program (not the Serum dex itself).
+ program_id = Pubkey.from_string("22Y43yTVxuUkoRKdm9thyRhQ3SdgQS7c7kB6UNCiaczD")
+ program = await Program.at(
+ program_id, provider
+ )
+ print(program.idl.name) # swap
+ await program.close()
+
+
+asyncio.run(main())
+
+
+````
+
+## Instantiating user-defined types with `program.type`
+
+### Enums
+
+Suppose we have an instruction that expects an Enum called `Side`,
+with variants `Buy` and `Sell`. The `Program` object has a `.type`
+namespace to make it easy to use this enum:
+
+````python
+await program.rpc["my_func"](program.type["Side"].Buy())
+
+````
+See [test_token_proxy.py](https://github.com/kevinheavey/anchorpy/blob/main/tests/test_token_proxy.py)
+for a more concrete example.
+
+### Structs
+
+`.type` also allows us to build structs defined in the IDL.
+See this snippet from [test_multisig.py](https://github.com/kevinheavey/anchorpy/blob/main/tests/test_multisig.py):
+
+````python
+program.type["TransactionAccount"](
+ pubkey=multisig.pubkey(),
+ is_writable=True,
+ is_signer=False,
+)
+
+````
+
+## Bulk-fetching data with `.fetch_multiple`
+
+You can use `.fetch_multiple` to get deserialized account data
+for many accounts at once. Look at this example from `test_misc.py`:
+
+````python
+n_accounts = 200
+pubkeys = [initialized_keypair.pubkey()] * n_accounts # noqa: WPS435
+data_accounts = await program.account["Data"].fetch_multiple(
+ pubkeys, batch_size=2
+)
+
+````
+
+The above example fetches data for the same pubkey 200 times which is
+not very interesting, but it could just as easily be fetching 200
+different accounts. The `.fetch_multiple` method uses async batch RPC requests
+and `getMultipleAccounts` so it's quite efficient.
+
+!!! warning
+ Be mindful of your RPC provider when fetching data, and plan out how
+ many requests you'll end up sending to the RPC node. You can reliably
+ fetch around 300 public keys in one HTTP request.
diff --git a/basics/anchorpy-main/docs/dynamic_client/index.md b/basics/anchorpy-main/docs/dynamic_client/index.md
new file mode 100644
index 0000000..517022a
--- /dev/null
+++ b/basics/anchorpy-main/docs/dynamic_client/index.md
@@ -0,0 +1,165 @@
+# Tutorial
+
+
+!!! note
+ It is recommended to use the generated client instead of the dynamic client where possible, as it is easier to
+ work with and comes with proper type hints.
+
+This tutorial takes the JS snippets from the official Anchor tutorial
+and shows how to achieve the same thing using AnchorPy.
+
+## [A Minimal Example](https://project-serum.github.io/anchor/tutorials/tutorial-0.html)
+This section covers the `basic-0` tutorial:
+### [Generating a Client](https://project-serum.github.io/anchor/tutorials/tutorial-0.html#generating-a-client)
+Here is how we generate a client from an IDL and use it to interact with a smart contract.
+
+
+=== "Python"
+ ````python
+ from pathlib import Path
+ import asyncio
+ import json
+ from solders.pubkey import Pubkey
+ from anchorpy import Idl, Program
+
+ async def main():
+ # Read the generated IDL.
+ with Path("target/idl/basic_0.json").open() as f:
+ raw_idl = f.read()
+ idl = Idl.from_json(raw_idl)
+ # Address of the deployed program.
+ program_id = Pubkey.from_string("")
+ # Generate the program client from IDL.
+ async with Program(idl, program_id) as program:
+ # Execute the RPC.
+ await program.rpc["initialize"]()
+ # If we don't use the context manager, we need to
+ # close the underlying http client, otherwise we get warnings.
+ # await program.close()
+
+ asyncio.run(main())
+
+ ````
+
+=== "JS"
+ ````javascript
+ // Read the generated IDL.
+ const idl = JSON.parse(require('fs').readFileSync('./target/idl/basic_0.json', 'utf8'));
+
+ // Address of the deployed program.
+ const programId = new anchor.web3.Pubkey('');
+
+ // Generate the program client from IDL.
+ const program = new anchor.Program(idl, programId);
+
+ // Execute the RPC.
+ await program.rpc.initialize();
+
+ ````
+
+Note the differences between Python and JS here:
+
+- We call `program.rpc["initialize"]()` instead of `program.rpc.initialize()`
+- We call `program.close()` to close the HTTP connection.
+
+### [Workspaces](https://project-serum.github.io/anchor/tutorials/tutorial-0.html#workspaces)
+
+Here is how workspaces look in AnchorPy:
+
+
+=== "Python"
+ ````python
+ import asyncio
+ from anchorpy import create_workspace, close_workspace
+
+ async def main():
+ # Read the deployed program from the workspace.
+ workspace = create_workspace()
+ program = workspace["basic_0"]
+ # Execute the RPC.
+ await program.rpc["initialize"]()
+ # Close all HTTP clients in the workspace, otherwise we get warnings.
+ await close_workspace(workspace)
+
+ asyncio.run(main())
+
+ ````
+
+=== "JS"
+ ````javascript
+ // Read the deployed program from the workspace.
+ const program = anchor.workspace.Basic0;
+
+ // Execute the RPC.
+ await program.rpc.initialize();
+
+ ````
+
+Note the differences between Python and JS:
+
+- Workspace instantiation is explicit: we have to call the `create_workspace` function.
+ - Note however that AnchorPy provides the `workspace_fixture` factory for convenience.
+ See the [testing](../testing/index.md) section for more.
+- We have a `close_workspace` function that calls `close_program` on all the programs
+in the workspace.
+- The workspace is called `basic_0` instead of `Basic0`. This is because AnchorPy uses snake case 🐍
+!!! Note
+ AnchorPy uses the same case convention as Rust, so names should look just like they do in `lib.rs`.
+ If you're unsure of a name, check `program.idl`: it shows how AnchorPy sees the IDL after parsing
+ it and converting some cases.
+
+## [Arguments and Accounts](https://project-serum.github.io/anchor/tutorials/tutorial-1.html)
+### [Creating and Initializing Accounts](https://project-serum.github.io/anchor/tutorials/tutorial-1.html#creating-and-initializing-accounts)
+
+Here is how we call an RPC function with arguments.
+As in the main Anchor tutorial, we will use `anchor/tutorial/examples/basic-1`:
+
+=== "Python"
+ ````python
+ import asyncio
+ from solders.keypair import Keypair
+ from solders.system_program import ID as SYS_PROGRAM_ID
+ from anchorpy import create_workspace, close_workspace, Context
+
+ async def main():
+ # Read the deployed program from the workspace.
+ workspace = create_workspace()
+ # The program to execute.
+ program = workspace["basic_1"]
+ # The Account to create.
+ my_account = Keypair()
+ # Execute the RPC.
+ accounts = {
+ "my_account": my_account.pubkey(),
+ "user": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID
+ }
+ await program.rpc["initialize"](1234, ctx=Context(accounts=accounts, signers=[my_account]))
+ # Close all HTTP clients in the workspace, otherwise we get warnings.
+ await close_workspace(workspace)
+
+ asyncio.run(main())
+
+ ````
+
+=== "JS"
+ ````javascript
+ // The program to execute.
+ const program = anchor.workspace.Basic1;
+
+ // The Account to create.
+ const myAccount = anchor.web3.Keypair();
+
+ // Create the new account and initialize it with the program.
+ await program.rpc.initialize(new anchor.BN(1234), {
+ accounts: {
+ myAccount: myAccount.Pubkey,
+ user: provider.wallet.Pubkey,
+ systemProgram: SystemProgram.programId,
+ },
+ signers: [myAccount],
+ });
+
+ ````
+
+Note how AnchorPy uses an explicit `Context` object in contrast to TS/JS.
diff --git a/basics/anchorpy-main/docs/img/anchor.svg b/basics/anchorpy-main/docs/img/anchor.svg
new file mode 100644
index 0000000..aa184c5
--- /dev/null
+++ b/basics/anchorpy-main/docs/img/anchor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/basics/anchorpy-main/docs/img/logo.png b/basics/anchorpy-main/docs/img/logo.png
new file mode 100644
index 0000000..7ba560c
Binary files /dev/null and b/basics/anchorpy-main/docs/img/logo.png differ
diff --git a/basics/anchorpy-main/docs/index.md b/basics/anchorpy-main/docs/index.md
new file mode 100644
index 0000000..bb8c424
--- /dev/null
+++ b/basics/anchorpy-main/docs/index.md
@@ -0,0 +1,23 @@
+# Introduction
+
+
+
+
+---
+AnchorPy is the gateway to interacting with [Anchor](https://github.com/project-serum/anchor) programs in Python.
+It provides:
+
+- A [static client generator](clientgen)
+- A [dynamic client](dynamic_client) similar to `anchor-ts`
+- A [Pytest plugin](testing/#1-pytest-plugin)
+- A [CLI](cli) with various utilities for Anchor Python development.
+
+## Installation (requires Python >= 3.9)
+
+```shell
+pip install anchorpy[cli]
+```
+
+
+!!! note
+ These docs will assume you've read the [Anchor documentation](https://www.anchor-lang.com/) first.
diff --git a/basics/anchorpy-main/docs/js/custom.js b/basics/anchorpy-main/docs/js/custom.js
new file mode 100644
index 0000000..45243eb
--- /dev/null
+++ b/basics/anchorpy-main/docs/js/custom.js
@@ -0,0 +1,105 @@
+document.querySelectorAll(".use-termynal").forEach(node => {
+ node.style.display = "block";
+ new Termynal(node, {
+ lineDelay: 500
+ });
+});
+const progressLiteralStart = "---> 100%";
+const promptLiteralStart = "$ ";
+const customPromptLiteralStart = "# ";
+const termynalActivateClass = "termy";
+let termynals = [];
+
+function createTermynals() {
+ document
+ .querySelectorAll(`.${termynalActivateClass} .highlight`)
+ .forEach(node => {
+ const text = node.textContent;
+ const lines = text.split("\n");
+ const useLines = [];
+ let buffer = [];
+ function saveBuffer() {
+ if (buffer.length) {
+ let isBlankSpace = true;
+ buffer.forEach(line => {
+ if (line) {
+ isBlankSpace = false;
+ }
+ });
+ dataValue = {};
+ if (isBlankSpace) {
+ dataValue["delay"] = 0;
+ }
+ if (buffer[buffer.length - 1] === "") {
+ // A last single won't have effect
+ // so put an additional one
+ buffer.push("");
+ }
+ const bufferValue = buffer.join(" ");
+ dataValue["value"] = bufferValue;
+ useLines.push(dataValue);
+ buffer = [];
+ }
+ }
+ for (let line of lines) {
+ if (line === progressLiteralStart) {
+ saveBuffer();
+ useLines.push({
+ type: "progress"
+ });
+ } else if (line.startsWith(promptLiteralStart)) {
+ saveBuffer();
+ const value = line.replace(promptLiteralStart, "").trimEnd();
+ useLines.push({
+ type: "input",
+ value: value
+ });
+ } else if (line.startsWith("// ")) {
+ saveBuffer();
+ const value = "💬 " + line.replace("// ", "").trimEnd();
+ useLines.push({
+ value: value,
+ class: "termynal-comment",
+ delay: 0
+ });
+ } else if (line.startsWith(customPromptLiteralStart)) {
+ saveBuffer();
+ const promptStart = line.indexOf(promptLiteralStart);
+ if (promptStart === -1) {
+ console.error("Custom prompt found but no end delimiter", line)
+ }
+ const prompt = line.slice(0, promptStart).replace(customPromptLiteralStart, "")
+ let value = line.slice(promptStart + promptLiteralStart.length);
+ useLines.push({
+ type: "input",
+ value: value,
+ prompt: prompt
+ });
+ } else {
+ buffer.push(line);
+ }
+ }
+ saveBuffer();
+ const div = document.createElement("div");
+ node.replaceWith(div);
+ const termynal = new Termynal(div, {
+ lineData: useLines,
+ noInit: true,
+ lineDelay: 500
+ });
+ termynals.push(termynal);
+ });
+}
+
+function loadVisibleTermynals() {
+ termynals = termynals.filter(termynal => {
+ if (termynal.container.getBoundingClientRect().top - innerHeight <= 0) {
+ termynal.init();
+ return false;
+ }
+ return true;
+ });
+}
+window.addEventListener("scroll", loadVisibleTermynals);
+createTermynals();
+loadVisibleTermynals();
diff --git a/basics/anchorpy-main/docs/js/termynal.js b/basics/anchorpy-main/docs/js/termynal.js
new file mode 100644
index 0000000..a26c870
--- /dev/null
+++ b/basics/anchorpy-main/docs/js/termynal.js
@@ -0,0 +1,264 @@
+/**
+ * termynal.js
+ * A lightweight, modern and extensible animated terminal window, using
+ * async/await.
+ *
+ * @author Ines Montani
+ * @version 0.0.1
+ * @license MIT
+ */
+
+'use strict';
+
+/** Generate a terminal widget. */
+class Termynal {
+ /**
+ * Construct the widget's settings.
+ * @param {(string|Node)=} container - Query selector or container element.
+ * @param {Object=} options - Custom settings.
+ * @param {string} options.prefix - Prefix to use for data attributes.
+ * @param {number} options.startDelay - Delay before animation, in ms.
+ * @param {number} options.typeDelay - Delay between each typed character, in ms.
+ * @param {number} options.lineDelay - Delay between each line, in ms.
+ * @param {number} options.progressLength - Number of characters displayed as progress bar.
+ * @param {string} options.progressChar – Character to use for progress bar, defaults to █.
+ * @param {number} options.progressPercent - Max percent of progress.
+ * @param {string} options.cursor – Character to use for cursor, defaults to ▋.
+ * @param {Object[]} lineData - Dynamically loaded line data objects.
+ * @param {boolean} options.noInit - Don't initialise the animation.
+ */
+ constructor(container = '#termynal', options = {}) {
+ this.container = (typeof container === 'string') ? document.querySelector(container) : container;
+ this.pfx = `data-${options.prefix || 'ty'}`;
+ this.originalStartDelay = this.startDelay = options.startDelay
+ || parseFloat(this.container.getAttribute(`${this.pfx}-startDelay`)) || 600;
+ this.originalTypeDelay = this.typeDelay = options.typeDelay
+ || parseFloat(this.container.getAttribute(`${this.pfx}-typeDelay`)) || 90;
+ this.originalLineDelay = this.lineDelay = options.lineDelay
+ || parseFloat(this.container.getAttribute(`${this.pfx}-lineDelay`)) || 1500;
+ this.progressLength = options.progressLength
+ || parseFloat(this.container.getAttribute(`${this.pfx}-progressLength`)) || 40;
+ this.progressChar = options.progressChar
+ || this.container.getAttribute(`${this.pfx}-progressChar`) || '█';
+ this.progressPercent = options.progressPercent
+ || parseFloat(this.container.getAttribute(`${this.pfx}-progressPercent`)) || 100;
+ this.cursor = options.cursor
+ || this.container.getAttribute(`${this.pfx}-cursor`) || '▋';
+ this.lineData = this.lineDataToElements(options.lineData || []);
+ this.loadLines()
+ if (!options.noInit) this.init()
+ }
+
+ loadLines() {
+ // Load all the lines and create the container so that the size is fixed
+ // Otherwise it would be changing and the user viewport would be constantly
+ // moving as she/he scrolls
+ const finish = this.generateFinish()
+ finish.style.visibility = 'hidden'
+ this.container.appendChild(finish)
+ // Appends dynamically loaded lines to existing line elements.
+ this.lines = [...this.container.querySelectorAll(`[${this.pfx}]`)].concat(this.lineData);
+ for (let line of this.lines) {
+ line.style.visibility = 'hidden'
+ this.container.appendChild(line)
+ }
+ const restart = this.generateRestart()
+ restart.style.visibility = 'hidden'
+ this.container.appendChild(restart)
+ this.container.setAttribute('data-termynal', '');
+ }
+
+ /**
+ * Initialise the widget, get lines, clear container and start animation.
+ */
+ init() {
+ /**
+ * Calculates width and height of Termynal container.
+ * If container is empty and lines are dynamically loaded, defaults to browser `auto` or CSS.
+ */
+ const containerStyle = getComputedStyle(this.container);
+ this.container.style.width = containerStyle.width !== '0px' ?
+ containerStyle.width : undefined;
+ this.container.style.minHeight = containerStyle.height !== '0px' ?
+ containerStyle.height : undefined;
+
+ this.container.setAttribute('data-termynal', '');
+ this.container.innerHTML = '';
+ for (let line of this.lines) {
+ line.style.visibility = 'visible'
+ }
+ this.start();
+ }
+
+ /**
+ * Start the animation and rener the lines depending on their data attributes.
+ */
+ async start() {
+ this.addFinish()
+ await this._wait(this.startDelay);
+
+ for (let line of this.lines) {
+ const type = line.getAttribute(this.pfx);
+ const delay = line.getAttribute(`${this.pfx}-delay`) || this.lineDelay;
+
+ if (type == 'input') {
+ line.setAttribute(`${this.pfx}-cursor`, this.cursor);
+ await this.type(line);
+ await this._wait(delay);
+ }
+
+ else if (type == 'progress') {
+ await this.progress(line);
+ await this._wait(delay);
+ }
+
+ else {
+ this.container.appendChild(line);
+ await this._wait(delay);
+ }
+
+ line.removeAttribute(`${this.pfx}-cursor`);
+ }
+ this.addRestart()
+ this.finishElement.style.visibility = 'hidden'
+ this.lineDelay = this.originalLineDelay
+ this.typeDelay = this.originalTypeDelay
+ this.startDelay = this.originalStartDelay
+ }
+
+ generateRestart() {
+ const restart = document.createElement('a')
+ restart.onclick = (e) => {
+ e.preventDefault()
+ this.container.innerHTML = ''
+ this.init()
+ }
+ restart.href = '#'
+ restart.setAttribute('data-terminal-control', '')
+ restart.innerHTML = "restart ↻"
+ return restart
+ }
+
+ generateFinish() {
+ const finish = document.createElement('a')
+ finish.onclick = (e) => {
+ e.preventDefault()
+ this.lineDelay = 0
+ this.typeDelay = 0
+ this.startDelay = 0
+ }
+ finish.href = '#'
+ finish.setAttribute('data-terminal-control', '')
+ finish.innerHTML = "fast →"
+ this.finishElement = finish
+ return finish
+ }
+
+ addRestart() {
+ const restart = this.generateRestart()
+ this.container.appendChild(restart)
+ }
+
+ addFinish() {
+ const finish = this.generateFinish()
+ this.container.appendChild(finish)
+ }
+
+ /**
+ * Animate a typed line.
+ * @param {Node} line - The line element to render.
+ */
+ async type(line) {
+ const chars = [...line.textContent];
+ line.textContent = '';
+ this.container.appendChild(line);
+
+ for (let char of chars) {
+ const delay = line.getAttribute(`${this.pfx}-typeDelay`) || this.typeDelay;
+ await this._wait(delay);
+ line.textContent += char;
+ }
+ }
+
+ /**
+ * Animate a progress bar.
+ * @param {Node} line - The line element to render.
+ */
+ async progress(line) {
+ const progressLength = line.getAttribute(`${this.pfx}-progressLength`)
+ || this.progressLength;
+ const progressChar = line.getAttribute(`${this.pfx}-progressChar`)
+ || this.progressChar;
+ const chars = progressChar.repeat(progressLength);
+ const progressPercent = line.getAttribute(`${this.pfx}-progressPercent`)
+ || this.progressPercent;
+ line.textContent = '';
+ this.container.appendChild(line);
+
+ for (let i = 1; i < chars.length + 1; i++) {
+ await this._wait(this.typeDelay);
+ const percent = Math.round(i / chars.length * 100);
+ line.textContent = `${chars.slice(0, i)} ${percent}%`;
+ if (percent > progressPercent) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Helper function for animation delays, called with `await`.
+ * @param {number} time - Timeout, in ms.
+ */
+ _wait(time) {
+ return new Promise(resolve => setTimeout(resolve, time));
+ }
+
+ /**
+ * Converts line data objects into line elements.
+ *
+ * @param {Object[]} lineData - Dynamically loaded lines.
+ * @param {Object} line - Line data object.
+ * @returns {Element[]} - Array of line elements.
+ */
+ lineDataToElements(lineData) {
+ return lineData.map(line => {
+ let div = document.createElement('div');
+ div.innerHTML = `${line.value || ''} `;
+
+ return div.firstElementChild;
+ });
+ }
+
+ /**
+ * Helper function for generating attributes string.
+ *
+ * @param {Object} line - Line data object.
+ * @returns {string} - String of attributes.
+ */
+ _attributes(line) {
+ let attrs = '';
+ for (let prop in line) {
+ // Custom add class
+ if (prop === 'class') {
+ attrs += ` class=${line[prop]} `
+ continue
+ }
+ if (prop === 'type') {
+ attrs += `${this.pfx}="${line[prop]}" `
+ } else if (prop !== 'value') {
+ attrs += `${this.pfx}-${prop}="${line[prop]}" `
+ }
+ }
+
+ return attrs;
+ }
+}
+
+/**
+* HTML API: If current script has container(s) specified, initialise Termynal.
+*/
+if (document.currentScript.hasAttribute('data-termynal-container')) {
+ const containers = document.currentScript.getAttribute('data-termynal-container');
+ containers.split('|')
+ .forEach(container => new Termynal(container))
+}
diff --git a/basics/anchorpy-main/docs/testing/index.md b/basics/anchorpy-main/docs/testing/index.md
new file mode 100644
index 0000000..8d516b5
--- /dev/null
+++ b/basics/anchorpy-main/docs/testing/index.md
@@ -0,0 +1,202 @@
+# Testing with AnchorPy
+
+## Approaches
+
+There are two ways to test Anchor programs using AnchorPy:
+
+1. Using the AnchorPy Pytest plugin.
+2. Using `anchor test` and modifying `Anchor.toml`.
+
+## 1. Pytest plugin
+
+AnchorPy provides a `workspace_fixture` function that creates a Pytest fixture.
+This fixture runs `anchor localnet` in the project root and shuts down the localnet
+when the tests are done.
+
+With this approach you're just running regular Pytest tests.
+This lets you do some things that you can't do with `anchor test`,
+like integrating closely with your IDE or opening a debugger when a test fails (`pytest --pdb`).
+
+Here's how it looks with the `basic-1` tests:
+
+```python
+from pytest import fixture, mark
+from solders.keypair import Keypair
+from solders.system_program import ID as SYS_PROGRAM_ID
+
+from anchorpy import Context, Program, workspace_fixture, WorkspaceType
+
+workspace = workspace_fixture("anchor/examples/tutorial/basic-1")
+
+# Since our other fixtures have module scope, we need to define
+# this event_loop fixture and give it module scope otherwise
+# pytest-asyncio will break.
+
+@fixture(scope="module")
+def event_loop():
+ """Create an instance of the default event loop for each test case."""
+ loop = asyncio.get_event_loop_policy().new_event_loop()
+ yield loop
+ loop.close()
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ """Create a Program instance."""
+ return workspace["basic_1"]
+
+
+@fixture(scope="module")
+async def initialized_account(program: Program) -> Keypair:
+ """Generate a keypair and initialize it."""
+ my_account = Keypair()
+ await program.rpc["initialize"](
+ 1234,
+ ctx=Context(
+ accounts={
+ "my_account": my_account.pubkey(),
+ "user": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[my_account],
+ ),
+ )
+ return my_account
+
+
+@mark.asyncio
+async def test_create_and_initialize_account(
+ program: Program,
+ initialized_account: Keypair,
+) -> None:
+ """Test creating and initializing account in single tx."""
+ account = await program.account["MyAccount"].fetch(initialized_account.pubkey())
+ assert account.data == 1234
+
+
+@mark.asyncio
+async def test_update_previously_created_account(
+ initialized_account: Keypair,
+ program: Program,
+) -> None:
+ """Test updating a previously created account."""
+ await program.rpc["update"](
+ 4321,
+ ctx=Context(accounts={"my_account": initialized_account.pubkey()}),
+ )
+ account = await program.account["MyAccount"].fetch(initialized_account.pubkey())
+ assert account.data == 4321
+
+```
+
+You can just run these tests with `pytest` (or have your IDE run them).
+!!! note
+ There is also a lower-level `localnet_fixture` function that sets up a localnet for a
+ particular project but doesn't return a workspace.
+
+## 2. Anchor test
+
+
+Anchor lets you run whatever tests you want using the `[scripts]` section of `Anchor.toml`.
+This means we can call Pytest inside the `anchor test` workflow. This is more limited
+than the Pytest plugin but is more like the standard Anchor way of doing things.
+
+Here's how the `basic-1` tests look using `anchor test` and Pytest (but not the ):
+
+```python
+# test_basic_1.py
+import asyncio
+from pathlib import Path
+from pytest import fixture, mark
+from anchorpy import create_workspace, close_workspace, Context, Program
+from solders.keypair import Keypair
+from solders.system_program import ID as SYS_PROGRAM_ID
+
+
+# Since our other fixtures have module scope, we need to define
+# this event_loop fixture and give it module scope otherwise
+# pytest-asyncio will break.
+
+@fixture(scope="module")
+def event_loop():
+ """Create an instance of the default event loop for each test case."""
+ loop = asyncio.get_event_loop_policy().new_event_loop()
+ yield loop
+ loop.close()
+
+
+@fixture(scope="module")
+async def program() -> Program:
+ workspace = create_workspace()
+ yield workspace["basic_1"]
+ await close_workspace(workspace)
+
+
+@fixture(scope="module")
+async def initialized_account(program: Program) -> Keypair:
+ my_account = Keypair()
+ await program.rpc["initialize"](
+ 1234,
+ ctx=Context(
+ accounts={
+ "my_account": my_account.pubkey(),
+ "user": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[my_account],
+ ),
+ )
+ return my_account
+
+
+@mark.asyncio
+async def test_create_and_initialize_account(
+ program: Program, initialized_account: Keypair
+) -> None:
+ """Test creating and initializing account in single tx."""
+ account = await program.account["MyAccount"].fetch(initialized_account.pubkey())
+ assert account.data == 1234
+
+
+@mark.asyncio
+async def test_update_previously_created_account(
+ initialized_account: Keypair, program: Program
+) -> None:
+ """Test updating a previously created account."""
+ await program.rpc["update"](
+ 4321, ctx=Context(accounts={"myAccount": initialized_account.pubkey()})
+ )
+ account = await program.account["MyAccount"].fetch(initialized_account.pubkey())
+ assert account.data == 4321
+
+```
+
+Just paste this code into a file called `test_basic_1.py`
+in `anchor/examples/tutorial/basic-1/tests/`, and change the `scripts` section of `Anchor.toml`
+to look like this:
+
+```toml
+[scripts]
+test = "pytest"
+
+```
+
+Then run `anchor test` and voila!.
+
+!!! note
+ You must have `pytest-asyncio` installed for `test_basic_1.py` to work.
+
+## Bankrun Integration
+
+AnchorPy comes with a `bankrun_fixture` to help use
+[`solders.bankrun`](https://kevinheavey.github.io/solders/examples/bankrun.html) in tests.
+
+If you haven't heard, `bankrun` is a much faster and more convenient alternative to
+`solana-test-validator`. Long test suites are about 40 times faster with `bankrun`,
+and for short test suites the difference is even bigger because `bankrun` has neglible
+startup time.
+
+`bankrun_fixture` calls `bankrun.start()` and deploys all the programs in the current
+Anchor workspace to the test envioronment.
+Check out [this example](https://github.com/kevinheavey/anchorpy/blob/main/tests/test_basic_3_bankrun.py).
+
diff --git a/basics/anchorpy-main/examples/client-gen/basic_2/__init__.py b/basics/anchorpy-main/examples/client-gen/basic_2/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/basics/anchorpy-main/examples/client-gen/basic_2/accounts/__init__.py b/basics/anchorpy-main/examples/client-gen/basic_2/accounts/__init__.py
new file mode 100644
index 0000000..4917931
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/basic_2/accounts/__init__.py
@@ -0,0 +1 @@
+from .counter import Counter, CounterJSON
diff --git a/basics/anchorpy-main/examples/client-gen/basic_2/accounts/counter.py b/basics/anchorpy-main/examples/client-gen/basic_2/accounts/counter.py
new file mode 100644
index 0000000..c6712f4
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/basic_2/accounts/counter.py
@@ -0,0 +1,87 @@
+import typing
+from dataclasses import dataclass
+from solders.pubkey import Pubkey
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+import borsh_construct as borsh
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.error import AccountInvalidDiscriminator
+from anchorpy.utils.rpc import get_multiple_accounts
+from anchorpy.borsh_extension import BorshPubkey
+from ..program_id import PROGRAM_ID
+
+
+class CounterJSON(typing.TypedDict):
+ authority: str
+ count: int
+
+
+@dataclass
+class Counter:
+ discriminator: typing.ClassVar = b"\xff\xb0\x04\xf5\xbc\xfd|\x19"
+ layout: typing.ClassVar = borsh.CStruct(
+ "authority" / BorshPubkey, "count" / borsh.U64
+ )
+ authority: Pubkey
+ count: int
+
+ @classmethod
+ async def fetch(
+ cls,
+ conn: AsyncClient,
+ address: Pubkey,
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.Optional["Counter"]:
+ resp = await conn.get_account_info(address, commitment=commitment)
+ info = resp.value
+ if info is None:
+ return None
+ if info.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ bytes_data = info.data
+ return cls.decode(bytes_data)
+
+ @classmethod
+ async def fetch_multiple(
+ cls,
+ conn: AsyncClient,
+ addresses: list[Pubkey],
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.List[typing.Optional["Counter"]]:
+ infos = await get_multiple_accounts(conn, addresses, commitment=commitment)
+ res: typing.List[typing.Optional["Counter"]] = []
+ for info in infos:
+ if info is None:
+ res.append(None)
+ continue
+ if info.account.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ res.append(cls.decode(info.account.data))
+ return res
+
+ @classmethod
+ def decode(cls, data: bytes) -> "Counter":
+ if data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator:
+ raise AccountInvalidDiscriminator(
+ "The discriminator for this account is invalid"
+ )
+ dec = Counter.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])
+ return cls(
+ authority=dec.authority,
+ count=dec.count,
+ )
+
+ def to_json(self) -> CounterJSON:
+ return {
+ "authority": str(self.authority),
+ "count": self.count,
+ }
+
+ @classmethod
+ def from_json(cls, obj: CounterJSON) -> "Counter":
+ return cls(
+ authority=Pubkey.from_string(obj["authority"]),
+ count=obj["count"],
+ )
diff --git a/basics/anchorpy-main/examples/client-gen/basic_2/errors/__init__.py b/basics/anchorpy-main/examples/client-gen/basic_2/errors/__init__.py
new file mode 100644
index 0000000..b453d3f
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/basic_2/errors/__init__.py
@@ -0,0 +1,26 @@
+import typing
+import re
+from solders.transaction_status import (
+ InstructionErrorCustom,
+ TransactionErrorInstructionError,
+)
+from solana.rpc.core import RPCException
+from solders.rpc.errors import SendTransactionPreflightFailureMessage
+from anchorpy.error import extract_code_and_logs
+from ..program_id import PROGRAM_ID
+from . import anchor
+
+
+def from_code(code: int) -> typing.Optional[anchor.AnchorError]:
+ return anchor.from_code(code)
+
+
+error_re = re.compile(r"Program (\w+) failed: custom program error: (\w+)")
+
+
+def from_tx_error(error: RPCException) -> typing.Optional[anchor.AnchorError]:
+ err_info = error.args[0]
+ extracted = extract_code_and_logs(err_info, PROGRAM_ID)
+ if extracted is None:
+ return None
+ return from_code(extracted[0])
diff --git a/basics/anchorpy-main/examples/client-gen/basic_2/errors/anchor.py b/basics/anchorpy-main/examples/client-gen/basic_2/errors/anchor.py
new file mode 100644
index 0000000..3f266ef
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/basic_2/errors/anchor.py
@@ -0,0 +1,590 @@
+import typing
+from anchorpy.error import ProgramError
+
+
+class InstructionMissing(ProgramError):
+ def __init__(self):
+ super().__init__(100, "8 byte instruction identifier not provided")
+
+ code = 100
+ name = "InstructionMissing"
+ msg = "8 byte instruction identifier not provided"
+
+
+class InstructionFallbackNotFound(ProgramError):
+ def __init__(self):
+ super().__init__(101, "Fallback functions are not supported")
+
+ code = 101
+ name = "InstructionFallbackNotFound"
+ msg = "Fallback functions are not supported"
+
+
+class InstructionDidNotDeserialize(ProgramError):
+ def __init__(self):
+ super().__init__(102, "The program could not deserialize the given instruction")
+
+ code = 102
+ name = "InstructionDidNotDeserialize"
+ msg = "The program could not deserialize the given instruction"
+
+
+class InstructionDidNotSerialize(ProgramError):
+ def __init__(self):
+ super().__init__(103, "The program could not serialize the given instruction")
+
+ code = 103
+ name = "InstructionDidNotSerialize"
+ msg = "The program could not serialize the given instruction"
+
+
+class IdlInstructionStub(ProgramError):
+ def __init__(self):
+ super().__init__(1000, "The program was compiled without idl instructions")
+
+ code = 1000
+ name = "IdlInstructionStub"
+ msg = "The program was compiled without idl instructions"
+
+
+class IdlInstructionInvalidProgram(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 1001, "The transaction was given an invalid program for the IDL instruction"
+ )
+
+ code = 1001
+ name = "IdlInstructionInvalidProgram"
+ msg = "The transaction was given an invalid program for the IDL instruction"
+
+
+class ConstraintMut(ProgramError):
+ def __init__(self):
+ super().__init__(2000, "A mut constraint was violated")
+
+ code = 2000
+ name = "ConstraintMut"
+ msg = "A mut constraint was violated"
+
+
+class ConstraintHasOne(ProgramError):
+ def __init__(self):
+ super().__init__(2001, "A has_one constraint was violated")
+
+ code = 2001
+ name = "ConstraintHasOne"
+ msg = "A has_one constraint was violated"
+
+
+class ConstraintSigner(ProgramError):
+ def __init__(self):
+ super().__init__(2002, "A signer constraint was violated")
+
+ code = 2002
+ name = "ConstraintSigner"
+ msg = "A signer constraint was violated"
+
+
+class ConstraintRaw(ProgramError):
+ def __init__(self):
+ super().__init__(2003, "A raw constraint was violated")
+
+ code = 2003
+ name = "ConstraintRaw"
+ msg = "A raw constraint was violated"
+
+
+class ConstraintOwner(ProgramError):
+ def __init__(self):
+ super().__init__(2004, "An owner constraint was violated")
+
+ code = 2004
+ name = "ConstraintOwner"
+ msg = "An owner constraint was violated"
+
+
+class ConstraintRentExempt(ProgramError):
+ def __init__(self):
+ super().__init__(2005, "A rent exempt constraint was violated")
+
+ code = 2005
+ name = "ConstraintRentExempt"
+ msg = "A rent exempt constraint was violated"
+
+
+class ConstraintSeeds(ProgramError):
+ def __init__(self):
+ super().__init__(2006, "A seeds constraint was violated")
+
+ code = 2006
+ name = "ConstraintSeeds"
+ msg = "A seeds constraint was violated"
+
+
+class ConstraintExecutable(ProgramError):
+ def __init__(self):
+ super().__init__(2007, "An executable constraint was violated")
+
+ code = 2007
+ name = "ConstraintExecutable"
+ msg = "An executable constraint was violated"
+
+
+class ConstraintState(ProgramError):
+ def __init__(self):
+ super().__init__(2008, "A state constraint was violated")
+
+ code = 2008
+ name = "ConstraintState"
+ msg = "A state constraint was violated"
+
+
+class ConstraintAssociated(ProgramError):
+ def __init__(self):
+ super().__init__(2009, "An associated constraint was violated")
+
+ code = 2009
+ name = "ConstraintAssociated"
+ msg = "An associated constraint was violated"
+
+
+class ConstraintAssociatedInit(ProgramError):
+ def __init__(self):
+ super().__init__(2010, "An associated init constraint was violated")
+
+ code = 2010
+ name = "ConstraintAssociatedInit"
+ msg = "An associated init constraint was violated"
+
+
+class ConstraintClose(ProgramError):
+ def __init__(self):
+ super().__init__(2011, "A close constraint was violated")
+
+ code = 2011
+ name = "ConstraintClose"
+ msg = "A close constraint was violated"
+
+
+class ConstraintAddress(ProgramError):
+ def __init__(self):
+ super().__init__(2012, "An address constraint was violated")
+
+ code = 2012
+ name = "ConstraintAddress"
+ msg = "An address constraint was violated"
+
+
+class ConstraintZero(ProgramError):
+ def __init__(self):
+ super().__init__(2013, "Expected zero account discriminant")
+
+ code = 2013
+ name = "ConstraintZero"
+ msg = "Expected zero account discriminant"
+
+
+class ConstraintTokenMint(ProgramError):
+ def __init__(self):
+ super().__init__(2014, "A token mint constraint was violated")
+
+ code = 2014
+ name = "ConstraintTokenMint"
+ msg = "A token mint constraint was violated"
+
+
+class ConstraintTokenOwner(ProgramError):
+ def __init__(self):
+ super().__init__(2015, "A token owner constraint was violated")
+
+ code = 2015
+ name = "ConstraintTokenOwner"
+ msg = "A token owner constraint was violated"
+
+
+class ConstraintMintMintAuthority(ProgramError):
+ def __init__(self):
+ super().__init__(2016, "A mint mint authority constraint was violated")
+
+ code = 2016
+ name = "ConstraintMintMintAuthority"
+ msg = "A mint mint authority constraint was violated"
+
+
+class ConstraintMintFreezeAuthority(ProgramError):
+ def __init__(self):
+ super().__init__(2017, "A mint freeze authority constraint was violated")
+
+ code = 2017
+ name = "ConstraintMintFreezeAuthority"
+ msg = "A mint freeze authority constraint was violated"
+
+
+class ConstraintMintDecimals(ProgramError):
+ def __init__(self):
+ super().__init__(2018, "A mint decimals constraint was violated")
+
+ code = 2018
+ name = "ConstraintMintDecimals"
+ msg = "A mint decimals constraint was violated"
+
+
+class ConstraintSpace(ProgramError):
+ def __init__(self):
+ super().__init__(2019, "A space constraint was violated")
+
+ code = 2019
+ name = "ConstraintSpace"
+ msg = "A space constraint was violated"
+
+
+class RequireViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2500, "A require expression was violated")
+
+ code = 2500
+ name = "RequireViolated"
+ msg = "A require expression was violated"
+
+
+class RequireEqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2501, "A require_eq expression was violated")
+
+ code = 2501
+ name = "RequireEqViolated"
+ msg = "A require_eq expression was violated"
+
+
+class RequireKeysEqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2502, "A require_keys_eq expression was violated")
+
+ code = 2502
+ name = "RequireKeysEqViolated"
+ msg = "A require_keys_eq expression was violated"
+
+
+class RequireNeqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2503, "A require_neq expression was violated")
+
+ code = 2503
+ name = "RequireNeqViolated"
+ msg = "A require_neq expression was violated"
+
+
+class RequireKeysNeqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2504, "A require_keys_neq expression was violated")
+
+ code = 2504
+ name = "RequireKeysNeqViolated"
+ msg = "A require_keys_neq expression was violated"
+
+
+class RequireGtViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2505, "A require_gt expression was violated")
+
+ code = 2505
+ name = "RequireGtViolated"
+ msg = "A require_gt expression was violated"
+
+
+class RequireGteViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2506, "A require_gte expression was violated")
+
+ code = 2506
+ name = "RequireGteViolated"
+ msg = "A require_gte expression was violated"
+
+
+class AccountDiscriminatorAlreadySet(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3000, "The account discriminator was already set on this account"
+ )
+
+ code = 3000
+ name = "AccountDiscriminatorAlreadySet"
+ msg = "The account discriminator was already set on this account"
+
+
+class AccountDiscriminatorNotFound(ProgramError):
+ def __init__(self):
+ super().__init__(3001, "No 8 byte discriminator was found on the account")
+
+ code = 3001
+ name = "AccountDiscriminatorNotFound"
+ msg = "No 8 byte discriminator was found on the account"
+
+
+class AccountDiscriminatorMismatch(ProgramError):
+ def __init__(self):
+ super().__init__(3002, "8 byte discriminator did not match what was expected")
+
+ code = 3002
+ name = "AccountDiscriminatorMismatch"
+ msg = "8 byte discriminator did not match what was expected"
+
+
+class AccountDidNotDeserialize(ProgramError):
+ def __init__(self):
+ super().__init__(3003, "Failed to deserialize the account")
+
+ code = 3003
+ name = "AccountDidNotDeserialize"
+ msg = "Failed to deserialize the account"
+
+
+class AccountDidNotSerialize(ProgramError):
+ def __init__(self):
+ super().__init__(3004, "Failed to serialize the account")
+
+ code = 3004
+ name = "AccountDidNotSerialize"
+ msg = "Failed to serialize the account"
+
+
+class AccountNotEnoughKeys(ProgramError):
+ def __init__(self):
+ super().__init__(3005, "Not enough account keys given to the instruction")
+
+ code = 3005
+ name = "AccountNotEnoughKeys"
+ msg = "Not enough account keys given to the instruction"
+
+
+class AccountNotMutable(ProgramError):
+ def __init__(self):
+ super().__init__(3006, "The given account is not mutable")
+
+ code = 3006
+ name = "AccountNotMutable"
+ msg = "The given account is not mutable"
+
+
+class AccountOwnedByWrongProgram(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3007, "The given account is owned by a different program than expected"
+ )
+
+ code = 3007
+ name = "AccountOwnedByWrongProgram"
+ msg = "The given account is owned by a different program than expected"
+
+
+class InvalidProgramId(ProgramError):
+ def __init__(self):
+ super().__init__(3008, "Program ID was not as expected")
+
+ code = 3008
+ name = "InvalidProgramId"
+ msg = "Program ID was not as expected"
+
+
+class InvalidProgramExecutable(ProgramError):
+ def __init__(self):
+ super().__init__(3009, "Program account is not executable")
+
+ code = 3009
+ name = "InvalidProgramExecutable"
+ msg = "Program account is not executable"
+
+
+class AccountNotSigner(ProgramError):
+ def __init__(self):
+ super().__init__(3010, "The given account did not sign")
+
+ code = 3010
+ name = "AccountNotSigner"
+ msg = "The given account did not sign"
+
+
+class AccountNotSystemOwned(ProgramError):
+ def __init__(self):
+ super().__init__(3011, "The given account is not owned by the system program")
+
+ code = 3011
+ name = "AccountNotSystemOwned"
+ msg = "The given account is not owned by the system program"
+
+
+class AccountNotInitialized(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3012, "The program expected this account to be already initialized"
+ )
+
+ code = 3012
+ name = "AccountNotInitialized"
+ msg = "The program expected this account to be already initialized"
+
+
+class AccountNotProgramData(ProgramError):
+ def __init__(self):
+ super().__init__(3013, "The given account is not a program data account")
+
+ code = 3013
+ name = "AccountNotProgramData"
+ msg = "The given account is not a program data account"
+
+
+class AccountNotAssociatedTokenAccount(ProgramError):
+ def __init__(self):
+ super().__init__(3014, "The given account is not the associated token account")
+
+ code = 3014
+ name = "AccountNotAssociatedTokenAccount"
+ msg = "The given account is not the associated token account"
+
+
+class AccountSysvarMismatch(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3015, "The given public key does not match the required sysvar"
+ )
+
+ code = 3015
+ name = "AccountSysvarMismatch"
+ msg = "The given public key does not match the required sysvar"
+
+
+class StateInvalidAddress(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 4000, "The given state account does not have the correct address"
+ )
+
+ code = 4000
+ name = "StateInvalidAddress"
+ msg = "The given state account does not have the correct address"
+
+
+class Deprecated(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 5000, "The API being used is deprecated and should no longer be used"
+ )
+
+ code = 5000
+ name = "Deprecated"
+ msg = "The API being used is deprecated and should no longer be used"
+
+
+AnchorError = typing.Union[
+ InstructionMissing,
+ InstructionFallbackNotFound,
+ InstructionDidNotDeserialize,
+ InstructionDidNotSerialize,
+ IdlInstructionStub,
+ IdlInstructionInvalidProgram,
+ ConstraintMut,
+ ConstraintHasOne,
+ ConstraintSigner,
+ ConstraintRaw,
+ ConstraintOwner,
+ ConstraintRentExempt,
+ ConstraintSeeds,
+ ConstraintExecutable,
+ ConstraintState,
+ ConstraintAssociated,
+ ConstraintAssociatedInit,
+ ConstraintClose,
+ ConstraintAddress,
+ ConstraintZero,
+ ConstraintTokenMint,
+ ConstraintTokenOwner,
+ ConstraintMintMintAuthority,
+ ConstraintMintFreezeAuthority,
+ ConstraintMintDecimals,
+ ConstraintSpace,
+ RequireViolated,
+ RequireEqViolated,
+ RequireKeysEqViolated,
+ RequireNeqViolated,
+ RequireKeysNeqViolated,
+ RequireGtViolated,
+ RequireGteViolated,
+ AccountDiscriminatorAlreadySet,
+ AccountDiscriminatorNotFound,
+ AccountDiscriminatorMismatch,
+ AccountDidNotDeserialize,
+ AccountDidNotSerialize,
+ AccountNotEnoughKeys,
+ AccountNotMutable,
+ AccountOwnedByWrongProgram,
+ InvalidProgramId,
+ InvalidProgramExecutable,
+ AccountNotSigner,
+ AccountNotSystemOwned,
+ AccountNotInitialized,
+ AccountNotProgramData,
+ AccountNotAssociatedTokenAccount,
+ AccountSysvarMismatch,
+ StateInvalidAddress,
+ Deprecated,
+]
+ANCHOR_ERROR_MAP: dict[int, AnchorError] = {
+ 100: InstructionMissing(),
+ 101: InstructionFallbackNotFound(),
+ 102: InstructionDidNotDeserialize(),
+ 103: InstructionDidNotSerialize(),
+ 1000: IdlInstructionStub(),
+ 1001: IdlInstructionInvalidProgram(),
+ 2000: ConstraintMut(),
+ 2001: ConstraintHasOne(),
+ 2002: ConstraintSigner(),
+ 2003: ConstraintRaw(),
+ 2004: ConstraintOwner(),
+ 2005: ConstraintRentExempt(),
+ 2006: ConstraintSeeds(),
+ 2007: ConstraintExecutable(),
+ 2008: ConstraintState(),
+ 2009: ConstraintAssociated(),
+ 2010: ConstraintAssociatedInit(),
+ 2011: ConstraintClose(),
+ 2012: ConstraintAddress(),
+ 2013: ConstraintZero(),
+ 2014: ConstraintTokenMint(),
+ 2015: ConstraintTokenOwner(),
+ 2016: ConstraintMintMintAuthority(),
+ 2017: ConstraintMintFreezeAuthority(),
+ 2018: ConstraintMintDecimals(),
+ 2019: ConstraintSpace(),
+ 2500: RequireViolated(),
+ 2501: RequireEqViolated(),
+ 2502: RequireKeysEqViolated(),
+ 2503: RequireNeqViolated(),
+ 2504: RequireKeysNeqViolated(),
+ 2505: RequireGtViolated(),
+ 2506: RequireGteViolated(),
+ 3000: AccountDiscriminatorAlreadySet(),
+ 3001: AccountDiscriminatorNotFound(),
+ 3002: AccountDiscriminatorMismatch(),
+ 3003: AccountDidNotDeserialize(),
+ 3004: AccountDidNotSerialize(),
+ 3005: AccountNotEnoughKeys(),
+ 3006: AccountNotMutable(),
+ 3007: AccountOwnedByWrongProgram(),
+ 3008: InvalidProgramId(),
+ 3009: InvalidProgramExecutable(),
+ 3010: AccountNotSigner(),
+ 3011: AccountNotSystemOwned(),
+ 3012: AccountNotInitialized(),
+ 3013: AccountNotProgramData(),
+ 3014: AccountNotAssociatedTokenAccount(),
+ 3015: AccountSysvarMismatch(),
+ 4000: StateInvalidAddress(),
+ 5000: Deprecated(),
+}
+
+
+def from_code(code: int) -> typing.Optional[AnchorError]:
+ maybe_err = ANCHOR_ERROR_MAP.get(code)
+ if maybe_err is None:
+ return None
+ return maybe_err
diff --git a/basics/anchorpy-main/examples/client-gen/basic_2/instructions/__init__.py b/basics/anchorpy-main/examples/client-gen/basic_2/instructions/__init__.py
new file mode 100644
index 0000000..5d579c6
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/basic_2/instructions/__init__.py
@@ -0,0 +1,2 @@
+from .create import create, CreateArgs, CreateAccounts
+from .increment import increment, IncrementAccounts
diff --git a/basics/anchorpy-main/examples/client-gen/basic_2/instructions/create.py b/basics/anchorpy-main/examples/client-gen/basic_2/instructions/create.py
new file mode 100644
index 0000000..ed2b3fc
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/basic_2/instructions/create.py
@@ -0,0 +1,41 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.sysvar import RENT
+from solders.instruction import Instruction, AccountMeta
+from anchorpy.borsh_extension import BorshPubkey
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class CreateArgs(typing.TypedDict):
+ authority: Pubkey
+
+
+layout = borsh.CStruct("authority" / BorshPubkey)
+
+
+class CreateAccounts(typing.TypedDict):
+ counter: Pubkey
+
+
+def create(
+ args: CreateArgs,
+ accounts: CreateAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["counter"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=RENT, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\x18\x1e\xc8(\x05\x1c\x07w"
+ encoded_args = layout.build(
+ {
+ "authority": args["authority"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/examples/client-gen/basic_2/instructions/increment.py b/basics/anchorpy-main/examples/client-gen/basic_2/instructions/increment.py
new file mode 100644
index 0000000..4c5ea80
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/basic_2/instructions/increment.py
@@ -0,0 +1,27 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class IncrementAccounts(typing.TypedDict):
+ counter: Pubkey
+ authority: Pubkey
+
+
+def increment(
+ accounts: IncrementAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["counter"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["authority"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\x0b\x12h\th\xae;!"
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/examples/client-gen/basic_2/program_id.py b/basics/anchorpy-main/examples/client-gen/basic_2/program_id.py
new file mode 100644
index 0000000..649b93e
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/basic_2/program_id.py
@@ -0,0 +1,3 @@
+from solders.pubkey import Pubkey
+
+PROGRAM_ID = Pubkey.from_string("3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8")
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/__init__.py b/basics/anchorpy-main/examples/client-gen/tictactoe/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/accounts/__init__.py b/basics/anchorpy-main/examples/client-gen/tictactoe/accounts/__init__.py
new file mode 100644
index 0000000..fb255e9
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/accounts/__init__.py
@@ -0,0 +1 @@
+from .game import Game, GameJSON
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/accounts/game.py b/basics/anchorpy-main/examples/client-gen/tictactoe/accounts/game.py
new file mode 100644
index 0000000..3c26fb9
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/accounts/game.py
@@ -0,0 +1,135 @@
+import typing
+from dataclasses import dataclass
+from solders.pubkey import Pubkey
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+import borsh_construct as borsh
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.error import AccountInvalidDiscriminator
+from anchorpy.utils.rpc import get_multiple_accounts
+from anchorpy.borsh_extension import BorshPubkey
+from ..program_id import PROGRAM_ID
+from .. import types
+
+
+class GameJSON(typing.TypedDict):
+ players: list[str]
+ turn: int
+ board: list[list[typing.Optional[types.sign.SignJSON]]]
+ state: types.game_state.GameStateJSON
+
+
+@dataclass
+class Game:
+ discriminator: typing.ClassVar = b"\x1bZ\xa6}Jdy\x12"
+ layout: typing.ClassVar = borsh.CStruct(
+ "players" / BorshPubkey[2],
+ "turn" / borsh.U8,
+ "board" / borsh.Option(types.sign.layout)[3][3],
+ "state" / types.game_state.layout,
+ )
+ players: list[Pubkey]
+ turn: int
+ board: list[list[typing.Optional[types.sign.SignKind]]]
+ state: types.game_state.GameStateKind
+
+ @classmethod
+ async def fetch(
+ cls,
+ conn: AsyncClient,
+ address: Pubkey,
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.Optional["Game"]:
+ resp = await conn.get_account_info(address, commitment=commitment)
+ info = resp.value
+ if info is None:
+ return None
+ if info.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ bytes_data = info.data
+ return cls.decode(bytes_data)
+
+ @classmethod
+ async def fetch_multiple(
+ cls,
+ conn: AsyncClient,
+ addresses: list[Pubkey],
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.List[typing.Optional["Game"]]:
+ infos = await get_multiple_accounts(conn, addresses, commitment=commitment)
+ res: typing.List[typing.Optional["Game"]] = []
+ for info in infos:
+ if info is None:
+ res.append(None)
+ continue
+ if info.account.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ res.append(cls.decode(info.account.data))
+ return res
+
+ @classmethod
+ def decode(cls, data: bytes) -> "Game":
+ if data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator:
+ raise AccountInvalidDiscriminator(
+ "The discriminator for this account is invalid"
+ )
+ dec = Game.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])
+ return cls(
+ players=dec.players,
+ turn=dec.turn,
+ board=list(
+ map(
+ lambda item: list(
+ map(
+ lambda item: (
+ None if item is None else types.sign.from_decoded(item)
+ ),
+ item,
+ )
+ ),
+ dec.board,
+ )
+ ),
+ state=types.game_state.from_decoded(dec.state),
+ )
+
+ def to_json(self) -> GameJSON:
+ return {
+ "players": list(map(lambda item: str(item), self.players)),
+ "turn": self.turn,
+ "board": list(
+ map(
+ lambda item: list(
+ map(
+ lambda item: (None if item is None else item.to_json()),
+ item,
+ )
+ ),
+ self.board,
+ )
+ ),
+ "state": self.state.to_json(),
+ }
+
+ @classmethod
+ def from_json(cls, obj: GameJSON) -> "Game":
+ return cls(
+ players=list(map(lambda item: Pubkey.from_string(item), obj["players"])),
+ turn=obj["turn"],
+ board=list(
+ map(
+ lambda item: list(
+ map(
+ lambda item: (
+ None if item is None else types.sign.from_json(item)
+ ),
+ item,
+ )
+ ),
+ obj["board"],
+ )
+ ),
+ state=types.game_state.from_json(obj["state"]),
+ )
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/errors/__init__.py b/basics/anchorpy-main/examples/client-gen/tictactoe/errors/__init__.py
new file mode 100644
index 0000000..421993d
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/errors/__init__.py
@@ -0,0 +1,29 @@
+import typing
+import re
+from solders.transaction_status import (
+ InstructionErrorCustom,
+ TransactionErrorInstructionError,
+)
+from solana.rpc.core import RPCException
+from solders.rpc.errors import SendTransactionPreflightFailureMessage
+from anchorpy.error import extract_code_and_logs
+from ..program_id import PROGRAM_ID
+from . import anchor
+from . import custom
+
+
+def from_code(code: int) -> typing.Union[custom.CustomError, anchor.AnchorError, None]:
+ return custom.from_code(code) if code >= 6000 else anchor.from_code(code)
+
+
+error_re = re.compile(r"Program (\w+) failed: custom program error: (\w+)")
+
+
+def from_tx_error(
+ error: RPCException,
+) -> typing.Union[anchor.AnchorError, custom.CustomError, None]:
+ err_info = error.args[0]
+ extracted = extract_code_and_logs(err_info, PROGRAM_ID)
+ if extracted is None:
+ return None
+ return from_code(extracted[0])
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/errors/anchor.py b/basics/anchorpy-main/examples/client-gen/tictactoe/errors/anchor.py
new file mode 100644
index 0000000..3f266ef
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/errors/anchor.py
@@ -0,0 +1,590 @@
+import typing
+from anchorpy.error import ProgramError
+
+
+class InstructionMissing(ProgramError):
+ def __init__(self):
+ super().__init__(100, "8 byte instruction identifier not provided")
+
+ code = 100
+ name = "InstructionMissing"
+ msg = "8 byte instruction identifier not provided"
+
+
+class InstructionFallbackNotFound(ProgramError):
+ def __init__(self):
+ super().__init__(101, "Fallback functions are not supported")
+
+ code = 101
+ name = "InstructionFallbackNotFound"
+ msg = "Fallback functions are not supported"
+
+
+class InstructionDidNotDeserialize(ProgramError):
+ def __init__(self):
+ super().__init__(102, "The program could not deserialize the given instruction")
+
+ code = 102
+ name = "InstructionDidNotDeserialize"
+ msg = "The program could not deserialize the given instruction"
+
+
+class InstructionDidNotSerialize(ProgramError):
+ def __init__(self):
+ super().__init__(103, "The program could not serialize the given instruction")
+
+ code = 103
+ name = "InstructionDidNotSerialize"
+ msg = "The program could not serialize the given instruction"
+
+
+class IdlInstructionStub(ProgramError):
+ def __init__(self):
+ super().__init__(1000, "The program was compiled without idl instructions")
+
+ code = 1000
+ name = "IdlInstructionStub"
+ msg = "The program was compiled without idl instructions"
+
+
+class IdlInstructionInvalidProgram(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 1001, "The transaction was given an invalid program for the IDL instruction"
+ )
+
+ code = 1001
+ name = "IdlInstructionInvalidProgram"
+ msg = "The transaction was given an invalid program for the IDL instruction"
+
+
+class ConstraintMut(ProgramError):
+ def __init__(self):
+ super().__init__(2000, "A mut constraint was violated")
+
+ code = 2000
+ name = "ConstraintMut"
+ msg = "A mut constraint was violated"
+
+
+class ConstraintHasOne(ProgramError):
+ def __init__(self):
+ super().__init__(2001, "A has_one constraint was violated")
+
+ code = 2001
+ name = "ConstraintHasOne"
+ msg = "A has_one constraint was violated"
+
+
+class ConstraintSigner(ProgramError):
+ def __init__(self):
+ super().__init__(2002, "A signer constraint was violated")
+
+ code = 2002
+ name = "ConstraintSigner"
+ msg = "A signer constraint was violated"
+
+
+class ConstraintRaw(ProgramError):
+ def __init__(self):
+ super().__init__(2003, "A raw constraint was violated")
+
+ code = 2003
+ name = "ConstraintRaw"
+ msg = "A raw constraint was violated"
+
+
+class ConstraintOwner(ProgramError):
+ def __init__(self):
+ super().__init__(2004, "An owner constraint was violated")
+
+ code = 2004
+ name = "ConstraintOwner"
+ msg = "An owner constraint was violated"
+
+
+class ConstraintRentExempt(ProgramError):
+ def __init__(self):
+ super().__init__(2005, "A rent exempt constraint was violated")
+
+ code = 2005
+ name = "ConstraintRentExempt"
+ msg = "A rent exempt constraint was violated"
+
+
+class ConstraintSeeds(ProgramError):
+ def __init__(self):
+ super().__init__(2006, "A seeds constraint was violated")
+
+ code = 2006
+ name = "ConstraintSeeds"
+ msg = "A seeds constraint was violated"
+
+
+class ConstraintExecutable(ProgramError):
+ def __init__(self):
+ super().__init__(2007, "An executable constraint was violated")
+
+ code = 2007
+ name = "ConstraintExecutable"
+ msg = "An executable constraint was violated"
+
+
+class ConstraintState(ProgramError):
+ def __init__(self):
+ super().__init__(2008, "A state constraint was violated")
+
+ code = 2008
+ name = "ConstraintState"
+ msg = "A state constraint was violated"
+
+
+class ConstraintAssociated(ProgramError):
+ def __init__(self):
+ super().__init__(2009, "An associated constraint was violated")
+
+ code = 2009
+ name = "ConstraintAssociated"
+ msg = "An associated constraint was violated"
+
+
+class ConstraintAssociatedInit(ProgramError):
+ def __init__(self):
+ super().__init__(2010, "An associated init constraint was violated")
+
+ code = 2010
+ name = "ConstraintAssociatedInit"
+ msg = "An associated init constraint was violated"
+
+
+class ConstraintClose(ProgramError):
+ def __init__(self):
+ super().__init__(2011, "A close constraint was violated")
+
+ code = 2011
+ name = "ConstraintClose"
+ msg = "A close constraint was violated"
+
+
+class ConstraintAddress(ProgramError):
+ def __init__(self):
+ super().__init__(2012, "An address constraint was violated")
+
+ code = 2012
+ name = "ConstraintAddress"
+ msg = "An address constraint was violated"
+
+
+class ConstraintZero(ProgramError):
+ def __init__(self):
+ super().__init__(2013, "Expected zero account discriminant")
+
+ code = 2013
+ name = "ConstraintZero"
+ msg = "Expected zero account discriminant"
+
+
+class ConstraintTokenMint(ProgramError):
+ def __init__(self):
+ super().__init__(2014, "A token mint constraint was violated")
+
+ code = 2014
+ name = "ConstraintTokenMint"
+ msg = "A token mint constraint was violated"
+
+
+class ConstraintTokenOwner(ProgramError):
+ def __init__(self):
+ super().__init__(2015, "A token owner constraint was violated")
+
+ code = 2015
+ name = "ConstraintTokenOwner"
+ msg = "A token owner constraint was violated"
+
+
+class ConstraintMintMintAuthority(ProgramError):
+ def __init__(self):
+ super().__init__(2016, "A mint mint authority constraint was violated")
+
+ code = 2016
+ name = "ConstraintMintMintAuthority"
+ msg = "A mint mint authority constraint was violated"
+
+
+class ConstraintMintFreezeAuthority(ProgramError):
+ def __init__(self):
+ super().__init__(2017, "A mint freeze authority constraint was violated")
+
+ code = 2017
+ name = "ConstraintMintFreezeAuthority"
+ msg = "A mint freeze authority constraint was violated"
+
+
+class ConstraintMintDecimals(ProgramError):
+ def __init__(self):
+ super().__init__(2018, "A mint decimals constraint was violated")
+
+ code = 2018
+ name = "ConstraintMintDecimals"
+ msg = "A mint decimals constraint was violated"
+
+
+class ConstraintSpace(ProgramError):
+ def __init__(self):
+ super().__init__(2019, "A space constraint was violated")
+
+ code = 2019
+ name = "ConstraintSpace"
+ msg = "A space constraint was violated"
+
+
+class RequireViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2500, "A require expression was violated")
+
+ code = 2500
+ name = "RequireViolated"
+ msg = "A require expression was violated"
+
+
+class RequireEqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2501, "A require_eq expression was violated")
+
+ code = 2501
+ name = "RequireEqViolated"
+ msg = "A require_eq expression was violated"
+
+
+class RequireKeysEqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2502, "A require_keys_eq expression was violated")
+
+ code = 2502
+ name = "RequireKeysEqViolated"
+ msg = "A require_keys_eq expression was violated"
+
+
+class RequireNeqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2503, "A require_neq expression was violated")
+
+ code = 2503
+ name = "RequireNeqViolated"
+ msg = "A require_neq expression was violated"
+
+
+class RequireKeysNeqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2504, "A require_keys_neq expression was violated")
+
+ code = 2504
+ name = "RequireKeysNeqViolated"
+ msg = "A require_keys_neq expression was violated"
+
+
+class RequireGtViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2505, "A require_gt expression was violated")
+
+ code = 2505
+ name = "RequireGtViolated"
+ msg = "A require_gt expression was violated"
+
+
+class RequireGteViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2506, "A require_gte expression was violated")
+
+ code = 2506
+ name = "RequireGteViolated"
+ msg = "A require_gte expression was violated"
+
+
+class AccountDiscriminatorAlreadySet(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3000, "The account discriminator was already set on this account"
+ )
+
+ code = 3000
+ name = "AccountDiscriminatorAlreadySet"
+ msg = "The account discriminator was already set on this account"
+
+
+class AccountDiscriminatorNotFound(ProgramError):
+ def __init__(self):
+ super().__init__(3001, "No 8 byte discriminator was found on the account")
+
+ code = 3001
+ name = "AccountDiscriminatorNotFound"
+ msg = "No 8 byte discriminator was found on the account"
+
+
+class AccountDiscriminatorMismatch(ProgramError):
+ def __init__(self):
+ super().__init__(3002, "8 byte discriminator did not match what was expected")
+
+ code = 3002
+ name = "AccountDiscriminatorMismatch"
+ msg = "8 byte discriminator did not match what was expected"
+
+
+class AccountDidNotDeserialize(ProgramError):
+ def __init__(self):
+ super().__init__(3003, "Failed to deserialize the account")
+
+ code = 3003
+ name = "AccountDidNotDeserialize"
+ msg = "Failed to deserialize the account"
+
+
+class AccountDidNotSerialize(ProgramError):
+ def __init__(self):
+ super().__init__(3004, "Failed to serialize the account")
+
+ code = 3004
+ name = "AccountDidNotSerialize"
+ msg = "Failed to serialize the account"
+
+
+class AccountNotEnoughKeys(ProgramError):
+ def __init__(self):
+ super().__init__(3005, "Not enough account keys given to the instruction")
+
+ code = 3005
+ name = "AccountNotEnoughKeys"
+ msg = "Not enough account keys given to the instruction"
+
+
+class AccountNotMutable(ProgramError):
+ def __init__(self):
+ super().__init__(3006, "The given account is not mutable")
+
+ code = 3006
+ name = "AccountNotMutable"
+ msg = "The given account is not mutable"
+
+
+class AccountOwnedByWrongProgram(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3007, "The given account is owned by a different program than expected"
+ )
+
+ code = 3007
+ name = "AccountOwnedByWrongProgram"
+ msg = "The given account is owned by a different program than expected"
+
+
+class InvalidProgramId(ProgramError):
+ def __init__(self):
+ super().__init__(3008, "Program ID was not as expected")
+
+ code = 3008
+ name = "InvalidProgramId"
+ msg = "Program ID was not as expected"
+
+
+class InvalidProgramExecutable(ProgramError):
+ def __init__(self):
+ super().__init__(3009, "Program account is not executable")
+
+ code = 3009
+ name = "InvalidProgramExecutable"
+ msg = "Program account is not executable"
+
+
+class AccountNotSigner(ProgramError):
+ def __init__(self):
+ super().__init__(3010, "The given account did not sign")
+
+ code = 3010
+ name = "AccountNotSigner"
+ msg = "The given account did not sign"
+
+
+class AccountNotSystemOwned(ProgramError):
+ def __init__(self):
+ super().__init__(3011, "The given account is not owned by the system program")
+
+ code = 3011
+ name = "AccountNotSystemOwned"
+ msg = "The given account is not owned by the system program"
+
+
+class AccountNotInitialized(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3012, "The program expected this account to be already initialized"
+ )
+
+ code = 3012
+ name = "AccountNotInitialized"
+ msg = "The program expected this account to be already initialized"
+
+
+class AccountNotProgramData(ProgramError):
+ def __init__(self):
+ super().__init__(3013, "The given account is not a program data account")
+
+ code = 3013
+ name = "AccountNotProgramData"
+ msg = "The given account is not a program data account"
+
+
+class AccountNotAssociatedTokenAccount(ProgramError):
+ def __init__(self):
+ super().__init__(3014, "The given account is not the associated token account")
+
+ code = 3014
+ name = "AccountNotAssociatedTokenAccount"
+ msg = "The given account is not the associated token account"
+
+
+class AccountSysvarMismatch(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3015, "The given public key does not match the required sysvar"
+ )
+
+ code = 3015
+ name = "AccountSysvarMismatch"
+ msg = "The given public key does not match the required sysvar"
+
+
+class StateInvalidAddress(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 4000, "The given state account does not have the correct address"
+ )
+
+ code = 4000
+ name = "StateInvalidAddress"
+ msg = "The given state account does not have the correct address"
+
+
+class Deprecated(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 5000, "The API being used is deprecated and should no longer be used"
+ )
+
+ code = 5000
+ name = "Deprecated"
+ msg = "The API being used is deprecated and should no longer be used"
+
+
+AnchorError = typing.Union[
+ InstructionMissing,
+ InstructionFallbackNotFound,
+ InstructionDidNotDeserialize,
+ InstructionDidNotSerialize,
+ IdlInstructionStub,
+ IdlInstructionInvalidProgram,
+ ConstraintMut,
+ ConstraintHasOne,
+ ConstraintSigner,
+ ConstraintRaw,
+ ConstraintOwner,
+ ConstraintRentExempt,
+ ConstraintSeeds,
+ ConstraintExecutable,
+ ConstraintState,
+ ConstraintAssociated,
+ ConstraintAssociatedInit,
+ ConstraintClose,
+ ConstraintAddress,
+ ConstraintZero,
+ ConstraintTokenMint,
+ ConstraintTokenOwner,
+ ConstraintMintMintAuthority,
+ ConstraintMintFreezeAuthority,
+ ConstraintMintDecimals,
+ ConstraintSpace,
+ RequireViolated,
+ RequireEqViolated,
+ RequireKeysEqViolated,
+ RequireNeqViolated,
+ RequireKeysNeqViolated,
+ RequireGtViolated,
+ RequireGteViolated,
+ AccountDiscriminatorAlreadySet,
+ AccountDiscriminatorNotFound,
+ AccountDiscriminatorMismatch,
+ AccountDidNotDeserialize,
+ AccountDidNotSerialize,
+ AccountNotEnoughKeys,
+ AccountNotMutable,
+ AccountOwnedByWrongProgram,
+ InvalidProgramId,
+ InvalidProgramExecutable,
+ AccountNotSigner,
+ AccountNotSystemOwned,
+ AccountNotInitialized,
+ AccountNotProgramData,
+ AccountNotAssociatedTokenAccount,
+ AccountSysvarMismatch,
+ StateInvalidAddress,
+ Deprecated,
+]
+ANCHOR_ERROR_MAP: dict[int, AnchorError] = {
+ 100: InstructionMissing(),
+ 101: InstructionFallbackNotFound(),
+ 102: InstructionDidNotDeserialize(),
+ 103: InstructionDidNotSerialize(),
+ 1000: IdlInstructionStub(),
+ 1001: IdlInstructionInvalidProgram(),
+ 2000: ConstraintMut(),
+ 2001: ConstraintHasOne(),
+ 2002: ConstraintSigner(),
+ 2003: ConstraintRaw(),
+ 2004: ConstraintOwner(),
+ 2005: ConstraintRentExempt(),
+ 2006: ConstraintSeeds(),
+ 2007: ConstraintExecutable(),
+ 2008: ConstraintState(),
+ 2009: ConstraintAssociated(),
+ 2010: ConstraintAssociatedInit(),
+ 2011: ConstraintClose(),
+ 2012: ConstraintAddress(),
+ 2013: ConstraintZero(),
+ 2014: ConstraintTokenMint(),
+ 2015: ConstraintTokenOwner(),
+ 2016: ConstraintMintMintAuthority(),
+ 2017: ConstraintMintFreezeAuthority(),
+ 2018: ConstraintMintDecimals(),
+ 2019: ConstraintSpace(),
+ 2500: RequireViolated(),
+ 2501: RequireEqViolated(),
+ 2502: RequireKeysEqViolated(),
+ 2503: RequireNeqViolated(),
+ 2504: RequireKeysNeqViolated(),
+ 2505: RequireGtViolated(),
+ 2506: RequireGteViolated(),
+ 3000: AccountDiscriminatorAlreadySet(),
+ 3001: AccountDiscriminatorNotFound(),
+ 3002: AccountDiscriminatorMismatch(),
+ 3003: AccountDidNotDeserialize(),
+ 3004: AccountDidNotSerialize(),
+ 3005: AccountNotEnoughKeys(),
+ 3006: AccountNotMutable(),
+ 3007: AccountOwnedByWrongProgram(),
+ 3008: InvalidProgramId(),
+ 3009: InvalidProgramExecutable(),
+ 3010: AccountNotSigner(),
+ 3011: AccountNotSystemOwned(),
+ 3012: AccountNotInitialized(),
+ 3013: AccountNotProgramData(),
+ 3014: AccountNotAssociatedTokenAccount(),
+ 3015: AccountSysvarMismatch(),
+ 4000: StateInvalidAddress(),
+ 5000: Deprecated(),
+}
+
+
+def from_code(code: int) -> typing.Optional[AnchorError]:
+ maybe_err = ANCHOR_ERROR_MAP.get(code)
+ if maybe_err is None:
+ return None
+ return maybe_err
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/errors/custom.py b/basics/anchorpy-main/examples/client-gen/tictactoe/errors/custom.py
new file mode 100644
index 0000000..ea1923a
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/errors/custom.py
@@ -0,0 +1,66 @@
+import typing
+from anchorpy.error import ProgramError
+
+
+class TileOutOfBounds(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(6000, None)
+
+ code = 6000
+ name = "TileOutOfBounds"
+ msg = None
+
+
+class TileAlreadySet(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(6001, None)
+
+ code = 6001
+ name = "TileAlreadySet"
+ msg = None
+
+
+class GameAlreadyOver(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(6002, None)
+
+ code = 6002
+ name = "GameAlreadyOver"
+ msg = None
+
+
+class NotPlayersTurn(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(6003, None)
+
+ code = 6003
+ name = "NotPlayersTurn"
+ msg = None
+
+
+class GameAlreadyStarted(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(6004, None)
+
+ code = 6004
+ name = "GameAlreadyStarted"
+ msg = None
+
+
+CustomError = typing.Union[
+ TileOutOfBounds, TileAlreadySet, GameAlreadyOver, NotPlayersTurn, GameAlreadyStarted
+]
+CUSTOM_ERROR_MAP: dict[int, CustomError] = {
+ 6000: TileOutOfBounds(),
+ 6001: TileAlreadySet(),
+ 6002: GameAlreadyOver(),
+ 6003: NotPlayersTurn(),
+ 6004: GameAlreadyStarted(),
+}
+
+
+def from_code(code: int) -> typing.Optional[CustomError]:
+ maybe_err = CUSTOM_ERROR_MAP.get(code)
+ if maybe_err is None:
+ return None
+ return maybe_err
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/instructions/__init__.py b/basics/anchorpy-main/examples/client-gen/tictactoe/instructions/__init__.py
new file mode 100644
index 0000000..739e79e
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/instructions/__init__.py
@@ -0,0 +1,2 @@
+from .setup_game import setup_game, SetupGameArgs, SetupGameAccounts
+from .play import play, PlayArgs, PlayAccounts
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/instructions/play.py b/basics/anchorpy-main/examples/client-gen/tictactoe/instructions/play.py
new file mode 100644
index 0000000..ebd4f90
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/instructions/play.py
@@ -0,0 +1,41 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from .. import types
+from ..program_id import PROGRAM_ID
+
+
+class PlayArgs(typing.TypedDict):
+ tile: types.tile.Tile
+
+
+layout = borsh.CStruct("tile" / types.tile.Tile.layout)
+
+
+class PlayAccounts(typing.TypedDict):
+ game: Pubkey
+ player: Pubkey
+
+
+def play(
+ args: PlayArgs,
+ accounts: PlayAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["game"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["player"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xd5\x9d\xc1\x8e\xe48\xf8\x96"
+ encoded_args = layout.build(
+ {
+ "tile": args["tile"].to_encodable(),
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/instructions/setup_game.py b/basics/anchorpy-main/examples/client-gen/tictactoe/instructions/setup_game.py
new file mode 100644
index 0000000..15aad50
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/instructions/setup_game.py
@@ -0,0 +1,43 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.instruction import Instruction, AccountMeta
+from anchorpy.borsh_extension import BorshPubkey
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class SetupGameArgs(typing.TypedDict):
+ player_two: Pubkey
+
+
+layout = borsh.CStruct("player_two" / BorshPubkey)
+
+
+class SetupGameAccounts(typing.TypedDict):
+ game: Pubkey
+ player_one: Pubkey
+
+
+def setup_game(
+ args: SetupGameArgs,
+ accounts: SetupGameAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["game"], is_signer=True, is_writable=True),
+ AccountMeta(pubkey=accounts["player_one"], is_signer=True, is_writable=True),
+ AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xb4\xda\x80K:\xde#R"
+ encoded_args = layout.build(
+ {
+ "player_two": args["player_two"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/program_id.py b/basics/anchorpy-main/examples/client-gen/tictactoe/program_id.py
new file mode 100644
index 0000000..649b93e
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/program_id.py
@@ -0,0 +1,3 @@
+from solders.pubkey import Pubkey
+
+PROGRAM_ID = Pubkey.from_string("3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8")
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/types/__init__.py b/basics/anchorpy-main/examples/client-gen/tictactoe/types/__init__.py
new file mode 100644
index 0000000..ee1a6a2
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/types/__init__.py
@@ -0,0 +1,7 @@
+import typing
+from . import tile
+from .tile import Tile, TileJSON
+from . import game_state
+from .game_state import GameStateKind, GameStateJSON
+from . import sign
+from .sign import SignKind, SignJSON
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/types/game_state.py b/basics/anchorpy-main/examples/client-gen/tictactoe/types/game_state.py
new file mode 100644
index 0000000..09643ca
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/types/game_state.py
@@ -0,0 +1,129 @@
+from __future__ import annotations
+import typing
+from dataclasses import dataclass
+from solders.pubkey import Pubkey
+from anchorpy.borsh_extension import EnumForCodegen, BorshPubkey
+import borsh_construct as borsh
+
+
+class WonJSONValue(typing.TypedDict):
+ winner: str
+
+
+class WonValue(typing.TypedDict):
+ winner: Pubkey
+
+
+class ActiveJSON(typing.TypedDict):
+ kind: typing.Literal["Active"]
+
+
+class TieJSON(typing.TypedDict):
+ kind: typing.Literal["Tie"]
+
+
+class WonJSON(typing.TypedDict):
+ value: WonJSONValue
+ kind: typing.Literal["Won"]
+
+
+@dataclass
+class Active:
+ discriminator: typing.ClassVar = 0
+ kind: typing.ClassVar = "Active"
+
+ @classmethod
+ def to_json(cls) -> ActiveJSON:
+ return ActiveJSON(
+ kind="Active",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "Active": {},
+ }
+
+
+@dataclass
+class Tie:
+ discriminator: typing.ClassVar = 1
+ kind: typing.ClassVar = "Tie"
+
+ @classmethod
+ def to_json(cls) -> TieJSON:
+ return TieJSON(
+ kind="Tie",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "Tie": {},
+ }
+
+
+@dataclass
+class Won:
+ discriminator: typing.ClassVar = 2
+ kind: typing.ClassVar = "Won"
+ value: WonValue
+
+ def to_json(self) -> WonJSON:
+ return WonJSON(
+ kind="Won",
+ value={
+ "winner": str(self.value["winner"]),
+ },
+ )
+
+ def to_encodable(self) -> dict:
+ return {
+ "Won": {
+ "winner": self.value["winner"],
+ },
+ }
+
+
+GameStateKind = typing.Union[Active, Tie, Won]
+GameStateJSON = typing.Union[ActiveJSON, TieJSON, WonJSON]
+
+
+def from_decoded(obj: dict) -> GameStateKind:
+ if not isinstance(obj, dict):
+ raise ValueError("Invalid enum object")
+ if "Active" in obj:
+ return Active()
+ if "Tie" in obj:
+ return Tie()
+ if "Won" in obj:
+ val = obj["Won"]
+ return Won(
+ WonValue(
+ winner=val["winner"],
+ )
+ )
+ raise ValueError("Invalid enum object")
+
+
+def from_json(obj: GameStateJSON) -> GameStateKind:
+ if obj["kind"] == "Active":
+ return Active()
+ if obj["kind"] == "Tie":
+ return Tie()
+ if obj["kind"] == "Won":
+ won_json_value = typing.cast(WonJSONValue, obj["value"])
+ return Won(
+ WonValue(
+ winner=Pubkey.from_string(won_json_value["winner"]),
+ )
+ )
+ kind = obj["kind"]
+ raise ValueError(f"Unrecognized enum kind: {kind}")
+
+
+layout = EnumForCodegen(
+ "Active" / borsh.CStruct(),
+ "Tie" / borsh.CStruct(),
+ "Won" / borsh.CStruct("winner" / BorshPubkey),
+)
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/types/sign.py b/basics/anchorpy-main/examples/client-gen/tictactoe/types/sign.py
new file mode 100644
index 0000000..0577e31
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/types/sign.py
@@ -0,0 +1,75 @@
+from __future__ import annotations
+import typing
+from dataclasses import dataclass
+from anchorpy.borsh_extension import EnumForCodegen
+import borsh_construct as borsh
+
+
+class XJSON(typing.TypedDict):
+ kind: typing.Literal["X"]
+
+
+class OJSON(typing.TypedDict):
+ kind: typing.Literal["O"]
+
+
+@dataclass
+class X:
+ discriminator: typing.ClassVar = 0
+ kind: typing.ClassVar = "X"
+
+ @classmethod
+ def to_json(cls) -> XJSON:
+ return XJSON(
+ kind="X",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "X": {},
+ }
+
+
+@dataclass
+class O:
+ discriminator: typing.ClassVar = 1
+ kind: typing.ClassVar = "O"
+
+ @classmethod
+ def to_json(cls) -> OJSON:
+ return OJSON(
+ kind="O",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "O": {},
+ }
+
+
+SignKind = typing.Union[X, O]
+SignJSON = typing.Union[XJSON, OJSON]
+
+
+def from_decoded(obj: dict) -> SignKind:
+ if not isinstance(obj, dict):
+ raise ValueError("Invalid enum object")
+ if "X" in obj:
+ return X()
+ if "O" in obj:
+ return O()
+ raise ValueError("Invalid enum object")
+
+
+def from_json(obj: SignJSON) -> SignKind:
+ if obj["kind"] == "X":
+ return X()
+ if obj["kind"] == "O":
+ return O()
+ kind = obj["kind"]
+ raise ValueError(f"Unrecognized enum kind: {kind}")
+
+
+layout = EnumForCodegen("X" / borsh.CStruct(), "O" / borsh.CStruct())
diff --git a/basics/anchorpy-main/examples/client-gen/tictactoe/types/tile.py b/basics/anchorpy-main/examples/client-gen/tictactoe/types/tile.py
new file mode 100644
index 0000000..dcd9142
--- /dev/null
+++ b/basics/anchorpy-main/examples/client-gen/tictactoe/types/tile.py
@@ -0,0 +1,31 @@
+from __future__ import annotations
+import typing
+from dataclasses import dataclass
+from construct import Container
+import borsh_construct as borsh
+
+
+class TileJSON(typing.TypedDict):
+ row: int
+ column: int
+
+
+@dataclass
+class Tile:
+ layout: typing.ClassVar = borsh.CStruct("row" / borsh.U8, "column" / borsh.U8)
+ row: int
+ column: int
+
+ @classmethod
+ def from_decoded(cls, obj: Container) -> "Tile":
+ return cls(row=obj.row, column=obj.column)
+
+ def to_encodable(self) -> dict[str, typing.Any]:
+ return {"row": self.row, "column": self.column}
+
+ def to_json(self) -> TileJSON:
+ return {"row": self.row, "column": self.column}
+
+ @classmethod
+ def from_json(cls, obj: TileJSON) -> "Tile":
+ return cls(row=obj["row"], column=obj["column"])
diff --git a/basics/anchorpy-main/mkdocs.yml b/basics/anchorpy-main/mkdocs.yml
new file mode 100644
index 0000000..98b2c0a
--- /dev/null
+++ b/basics/anchorpy-main/mkdocs.yml
@@ -0,0 +1,64 @@
+site_name: AnchorPy
+theme:
+ name: material
+ icon:
+ logo: material/anchor
+ favicon: img/anchor.svg
+ features:
+ - navigation.tabs
+ - navigation.top
+ palette:
+ - scheme: default
+ primary: lime
+ toggle:
+ icon: material/toggle-switch-off-outline
+ name: Switch to dark mode
+ - scheme: slate
+ toggle:
+ icon: material/toggle-switch
+ name: Switch to light mode
+ custom_dir: overrides
+markdown_extensions:
+ - pymdownx.highlight
+ - pymdownx.superfences
+ - admonition
+ - pymdownx.snippets
+ - meta
+ - pymdownx.tabbed:
+ alternate_style: true
+repo_url: https://github.com/kevinheavey/anchorpy
+repo_name: kevinheavey/anchorpy
+site_url: https://kevinheavey.github.io/anchorpy/
+plugins:
+ - mkdocstrings:
+ handlers:
+ python:
+ selection:
+ filters:
+ - "!^_" # exlude all members starting with _
+ - "^__init__$" # but always include __init__ modules and methods
+ rendering:
+ show_root_heading: true
+ show_root_full_path: false
+ - search
+nav:
+ - index.md
+ - Client Generator:
+ - clientgen/index.md
+ - Dynamic Client:
+ - dynamic_client/index.md
+ - dynamic_client/comparison_with_anchor_ts.md
+ - dynamic_client/examples.md
+ - dynamic_client/api_reference.md
+ - Testing:
+ - testing/index.md
+ - CLI Reference:
+ - cli/index.md
+extra_css:
+ - css/mkdocstrings.css
+ - css/termynal.css
+ - css/custom.css
+extra_javascript:
+ - 'https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js'
+ - 'js/termynal.js'
+ - 'js/custom.js'
\ No newline at end of file
diff --git a/basics/anchorpy-main/mypy.ini b/basics/anchorpy-main/mypy.ini
new file mode 100644
index 0000000..ceaa6ec
--- /dev/null
+++ b/basics/anchorpy-main/mypy.ini
@@ -0,0 +1,29 @@
+[mypy]
+enable_recursive_aliases = True
+
+[mypy-pytest]
+ignore_missing_imports = True
+
+[mypy-xprocess]
+ignore_missing_imports = True
+
+[mypy-autoflake]
+ignore_missing_imports = True
+
+[mypy-pytest_xprocess]
+ignore_missing_imports = True
+
+[mypy-toolz]
+ignore_missing_imports = True
+
+[mypy-IPython]
+ignore_missing_imports = True
+
+[mypy-genpy]
+ignore_missing_imports = True
+
+[mypy-typer.*]
+ignore_missing_imports = True
+
+[mypy-black]
+ignore_missing_imports = True
diff --git a/basics/anchorpy-main/noxfile.py b/basics/anchorpy-main/noxfile.py
new file mode 100644
index 0000000..c7f28c7
--- /dev/null
+++ b/basics/anchorpy-main/noxfile.py
@@ -0,0 +1,9 @@
+# noqa: D100
+from nox_poetry import session # type: ignore
+
+
+@session
+def tests(session): # noqa: D103,WPS442
+ session.run_always("poetry", "install", "-E", "cli", external=True)
+ session.install(".")
+ session.run("pytest", "tests/unit", external=True)
diff --git a/basics/anchorpy-main/overrides/main.html b/basics/anchorpy-main/overrides/main.html
new file mode 100644
index 0000000..ad5b6ad
--- /dev/null
+++ b/basics/anchorpy-main/overrides/main.html
@@ -0,0 +1,5 @@
+{% extends "base.html" %}
+
+{% block extrahead %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/basics/anchorpy-main/poetry.lock b/basics/anchorpy-main/poetry.lock
new file mode 100644
index 0000000..6d4b53f
--- /dev/null
+++ b/basics/anchorpy-main/poetry.lock
@@ -0,0 +1,1883 @@
+# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
+
+[[package]]
+name = "anchorpy-core"
+version = "0.1.3"
+description = "Python bindings for Anchor Rust code"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "anchorpy_core-0.1.3-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c9af073115feaab9a7fd14bc9f0d19a87650042bd430e44e9c7714b18f5aeb3a"},
+ {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4511a3a9a0425a84305e56087b81969d2929ac642b2c1d6fb2a500c8f987d8d3"},
+ {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f5f37b3b75e891227beeb9f6ca35505317aa41e6f5a5ba92599aa3a4ecad9226"},
+ {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3690504cd40e5ea62aa78d23de3e93a8e8929fe50a86412253f9705640ce8993"},
+ {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8db7816180720041d7a756cd87e75fc9875c4e5b2c68faf8b440053d44d1a747"},
+ {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41134b3c08ed405c92e247ba77e966edf6859e741ae20109bcc3d02dfd0d37fc"},
+ {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:21a6cc01fb5932b9bbfcf3ab36e924c5a5f8897a4dfad73c96c2f6e934aeddf0"},
+ {file = "anchorpy_core-0.1.3-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:a6105025999e7270e0961e6c8a0436aa4218fc2d78ca056361d2aa2dffea46a3"},
+ {file = "anchorpy_core-0.1.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e9fe6f2e06dd0d3b27c079121a2bc0b495c7c1dc5026e81a2a0f947d7d840e5f"},
+ {file = "anchorpy_core-0.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:c952fe786c126e3c8b902d10c6d423085654001478e9a77600b105b3c66ac8ec"},
+ {file = "anchorpy_core-0.1.3.tar.gz", hash = "sha256:46a328ee5b6be730311ff673ad60e8e6e40e2eea7f8254c687ecff21416a2256"},
+]
+
+[package.dependencies]
+jsonalias = "0.1.1"
+
+[[package]]
+name = "anyio"
+version = "3.7.0"
+description = "High level compatibility layer for multiple asynchronous event loop implementations"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"},
+ {file = "anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce"},
+]
+
+[package.dependencies]
+exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
+idna = ">=2.8"
+sniffio = ">=1.1"
+
+[package.extras]
+doc = ["Sphinx (>=6.1.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme", "sphinxcontrib-jquery"]
+test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
+trio = ["trio (<0.22)"]
+
+[[package]]
+name = "appnope"
+version = "0.1.3"
+description = "Disable App Nap on macOS >= 10.9"
+optional = true
+python-versions = "*"
+files = [
+ {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
+ {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
+]
+
+[[package]]
+name = "asttokens"
+version = "2.2.1"
+description = "Annotate AST trees with source code positions"
+optional = true
+python-versions = "*"
+files = [
+ {file = "asttokens-2.2.1-py2.py3-none-any.whl", hash = "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"},
+ {file = "asttokens-2.2.1.tar.gz", hash = "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3"},
+]
+
+[package.dependencies]
+six = "*"
+
+[package.extras]
+test = ["astroid", "pytest"]
+
+[[package]]
+name = "attrs"
+version = "23.1.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
+ {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
+]
+
+[package.extras]
+cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
+dev = ["attrs[docs,tests]", "pre-commit"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
+tests = ["attrs[tests-no-zope]", "zope-interface"]
+tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+
+[[package]]
+name = "autoflake"
+version = "1.7.8"
+description = "Removes unused imports and unused variables"
+optional = true
+python-versions = ">=3.7"
+files = [
+ {file = "autoflake-1.7.8-py3-none-any.whl", hash = "sha256:46373ef69b6714f5064c923bb28bd797c4f8a9497f557d87fc36665c6d956b39"},
+ {file = "autoflake-1.7.8.tar.gz", hash = "sha256:e7e46372dee46fa1c97acf310d99d922b63d369718a270809d7c278d34a194cf"},
+]
+
+[package.dependencies]
+pyflakes = ">=1.1.0,<3"
+tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
+
+[[package]]
+name = "backcall"
+version = "0.2.0"
+description = "Specifications for callback functions passed in to an API"
+optional = true
+python-versions = "*"
+files = [
+ {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
+ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
+]
+
+[[package]]
+name = "based58"
+version = "0.1.1"
+description = "A fast Python library for Base58 and Base58Check"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "based58-0.1.1-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:745851792ce5fada615f05ec61d7f360d19c76950d1e86163b2293c63a5d43bc"},
+ {file = "based58-0.1.1-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:f8448a71678bd1edc0a464033695686461ab9d6d0bc3282cb29b94f883583572"},
+ {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:852c37206374a62c5d3ef7f6777746e2ad9106beec4551539e9538633385e613"},
+ {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3fb17f0aaaad0381c8b676623c870c1a56aca039e2a7c8416e65904d80a415f7"},
+ {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:06f3c40b358b0c6fc6fc614c43bb11ef851b6d04e519ac1eda2833420cb43799"},
+ {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a9db744be79c8087eebedbffced00c608b3ed780668ab3c59f1d16e72c84947"},
+ {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0506435e98836cc16e095e0d6dc428810e0acfb44bc2f3ac3e23e051a69c0e3e"},
+ {file = "based58-0.1.1-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8937e97fa8690164fd11a7c642f6d02df58facd2669ae7355e379ab77c48c924"},
+ {file = "based58-0.1.1-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14b01d91ac250300ca7f634e5bf70fb2b1b9aaa90cc14357943c7da525a35aff"},
+ {file = "based58-0.1.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6c03c7f0023981c7d52fc7aad23ed1f3342819358b9b11898d693c9ef4577305"},
+ {file = "based58-0.1.1-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:621269732454875510230b85053f462dffe7d7babecc8c553fdb488fd15810ff"},
+ {file = "based58-0.1.1-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:aba18f6c869fade1d1551fe398a376440771d6ce288c54cba71b7090cf08af02"},
+ {file = "based58-0.1.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ae7f17b67bf0c209da859a6b833504aa3b19dbf423cbd2369aa17e89299dc972"},
+ {file = "based58-0.1.1-cp37-abi3-win32.whl", hash = "sha256:d8dece575de525c1ad889d9ab239defb7a6ceffc48f044fe6e14a408fb05bef4"},
+ {file = "based58-0.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:ab85804a401a7b5a7141fbb14ef5b5f7d85288357d1d3f0085d47e616cef8f5a"},
+ {file = "based58-0.1.1.tar.gz", hash = "sha256:80804b346b34196c89dc7a3dc89b6021f910f4cd75aac41d433ca1880b1672dc"},
+]
+
+[[package]]
+name = "black"
+version = "22.12.0"
+description = "The uncompromising code formatter."
+optional = true
+python-versions = ">=3.7"
+files = [
+ {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"},
+ {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"},
+ {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"},
+ {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"},
+ {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"},
+ {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"},
+ {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"},
+ {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"},
+ {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"},
+ {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"},
+ {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"},
+ {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"},
+]
+
+[package.dependencies]
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
+typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "borsh-construct"
+version = "0.1.0"
+description = "Python implementation of Borsh serialization, built on the Construct library."
+optional = false
+python-versions = ">=3.8.3,<4.0.0"
+files = [
+ {file = "borsh-construct-0.1.0.tar.gz", hash = "sha256:c916758ceba70085d8f456a1cc26991b88cb64233d347767766473b651b37263"},
+ {file = "borsh_construct-0.1.0-py3-none-any.whl", hash = "sha256:f584c791e2a03f8fc36e6c13011a27bcaf028c9c54ba89cd70f485a7d1c687ed"},
+]
+
+[package.dependencies]
+construct-typing = ">=0.5.1,<0.6.0"
+sumtypes = ">=0.1a5,<0.2"
+
+[[package]]
+name = "bump2version"
+version = "1.0.1"
+description = "Version-bump your software with a single command!"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "bump2version-1.0.1-py2.py3-none-any.whl", hash = "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410"},
+ {file = "bump2version-1.0.1.tar.gz", hash = "sha256:762cb2bfad61f4ec8e2bdf452c7c267416f8c70dd9ecb1653fd0bbb01fa936e6"},
+]
+
+[[package]]
+name = "cachetools"
+version = "4.2.4"
+description = "Extensible memoizing collections and decorators"
+optional = false
+python-versions = "~=3.5"
+files = [
+ {file = "cachetools-4.2.4-py3-none-any.whl", hash = "sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1"},
+ {file = "cachetools-4.2.4.tar.gz", hash = "sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693"},
+]
+
+[[package]]
+name = "certifi"
+version = "2023.5.7"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
+ {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
+]
+
+[[package]]
+name = "cffi"
+version = "1.15.1"
+description = "Foreign Function Interface for Python calling C code."
+optional = false
+python-versions = "*"
+files = [
+ {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
+ {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"},
+ {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"},
+ {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"},
+ {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"},
+ {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"},
+ {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"},
+ {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"},
+ {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"},
+ {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"},
+ {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"},
+ {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"},
+ {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"},
+ {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"},
+ {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"},
+ {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"},
+ {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"},
+ {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"},
+ {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"},
+ {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"},
+ {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"},
+ {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"},
+ {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"},
+ {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"},
+ {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"},
+ {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"},
+ {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"},
+ {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"},
+ {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"},
+ {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"},
+ {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"},
+ {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"},
+ {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"},
+ {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"},
+ {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"},
+]
+
+[package.dependencies]
+pycparser = "*"
+
+[[package]]
+name = "charset-normalizer"
+version = "3.1.0"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = ">=3.7.0"
+files = [
+ {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
+ {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
+]
+
+[[package]]
+name = "click"
+version = "8.1.3"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
+ {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "construct"
+version = "2.10.68"
+description = "A powerful declarative symmetric parser/builder for binary data"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "construct-2.10.68.tar.gz", hash = "sha256:7b2a3fd8e5f597a5aa1d614c3bd516fa065db01704c72a1efaaeec6ef23d8b45"},
+]
+
+[package.extras]
+extras = ["arrow", "cloudpickle", "enum34", "lz4", "numpy", "ruamel.yaml"]
+
+[[package]]
+name = "construct-typing"
+version = "0.5.6"
+description = "Extension for the python package 'construct' that adds typing features"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "construct-typing-0.5.6.tar.gz", hash = "sha256:0dc501351cd6b308f15ec54e5fe7c0fbc07cc1530a1b77b4303062a0a93c1297"},
+ {file = "construct_typing-0.5.6-py3-none-any.whl", hash = "sha256:39c948329e880564e33521cba497b21b07967c465b9c9037d6334e2cffa1ced9"},
+]
+
+[package.dependencies]
+construct = "2.10.68"
+
+[[package]]
+name = "decorator"
+version = "5.1.1"
+description = "Decorators for Humans"
+optional = true
+python-versions = ">=3.5"
+files = [
+ {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
+ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.1.1"
+description = "Backport of PEP 654 (exception groups)"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
+ {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
+
+[[package]]
+name = "executing"
+version = "1.2.0"
+description = "Get the currently executing AST node of a frame, and other information"
+optional = true
+python-versions = "*"
+files = [
+ {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"},
+ {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"},
+]
+
+[package.extras]
+tests = ["asttokens", "littleutils", "pytest", "rich"]
+
+[[package]]
+name = "genpy"
+version = "2021.1"
+description = "AST-based generation of Python source code"
+optional = true
+python-versions = "~=3.6"
+files = [
+ {file = "genpy-2021.1.tar.gz", hash = "sha256:9bc062fa98c5c466ff464d8974be81a6bf67af9247b5e5176215ad1e81a6cdac"},
+]
+
+[package.dependencies]
+numpy = ">=1.6"
+pytools = ">=2015.1.2"
+
+[[package]]
+name = "ghp-import"
+version = "2.1.0"
+description = "Copy your docs directly to the gh-pages branch."
+optional = false
+python-versions = "*"
+files = [
+ {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
+ {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
+]
+
+[package.dependencies]
+python-dateutil = ">=2.8.1"
+
+[package.extras]
+dev = ["flake8", "markdown", "twine", "wheel"]
+
+[[package]]
+name = "h11"
+version = "0.14.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
+ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
+]
+
+[[package]]
+name = "httpcore"
+version = "0.16.3"
+description = "A minimal low-level HTTP client."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"},
+ {file = "httpcore-0.16.3.tar.gz", hash = "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb"},
+]
+
+[package.dependencies]
+anyio = ">=3.0,<5.0"
+certifi = "*"
+h11 = ">=0.13,<0.15"
+sniffio = "==1.*"
+
+[package.extras]
+http2 = ["h2 (>=3,<5)"]
+socks = ["socksio (==1.*)"]
+
+[[package]]
+name = "httpx"
+version = "0.23.3"
+description = "The next generation HTTP client."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"},
+ {file = "httpx-0.23.3.tar.gz", hash = "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9"},
+]
+
+[package.dependencies]
+certifi = "*"
+httpcore = ">=0.15.0,<0.17.0"
+rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]}
+sniffio = "*"
+
+[package.extras]
+brotli = ["brotli", "brotlicffi"]
+cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"]
+http2 = ["h2 (>=3,<5)"]
+socks = ["socksio (==1.*)"]
+
+[[package]]
+name = "idna"
+version = "3.4"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
+ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
+]
+
+[[package]]
+name = "importlib-metadata"
+version = "6.6.0"
+description = "Read metadata from Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
+ {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
+]
+
+[package.dependencies]
+zipp = ">=0.5"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+perf = ["ipython"]
+testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "ipython"
+version = "8.14.0"
+description = "IPython: Productive Interactive Computing"
+optional = true
+python-versions = ">=3.9"
+files = [
+ {file = "ipython-8.14.0-py3-none-any.whl", hash = "sha256:248aca623f5c99a6635bc3857677b7320b9b8039f99f070ee0d20a5ca5a8e6bf"},
+ {file = "ipython-8.14.0.tar.gz", hash = "sha256:1d197b907b6ba441b692c48cf2a3a2de280dc0ac91a3405b39349a50272ca0a1"},
+]
+
+[package.dependencies]
+appnope = {version = "*", markers = "sys_platform == \"darwin\""}
+backcall = "*"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+decorator = "*"
+jedi = ">=0.16"
+matplotlib-inline = "*"
+pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
+pickleshare = "*"
+prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0"
+pygments = ">=2.4.0"
+stack-data = "*"
+traitlets = ">=5"
+typing-extensions = {version = "*", markers = "python_version < \"3.10\""}
+
+[package.extras]
+all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
+black = ["black"]
+doc = ["docrepr", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"]
+kernel = ["ipykernel"]
+nbconvert = ["nbconvert"]
+nbformat = ["nbformat"]
+notebook = ["ipywidgets", "notebook"]
+parallel = ["ipyparallel"]
+qtconsole = ["qtconsole"]
+test = ["pytest (<7.1)", "pytest-asyncio", "testpath"]
+test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"]
+
+[[package]]
+name = "jedi"
+version = "0.18.2"
+description = "An autocompletion tool for Python that can be used for text editors."
+optional = true
+python-versions = ">=3.6"
+files = [
+ {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"},
+ {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"},
+]
+
+[package.dependencies]
+parso = ">=0.8.0,<0.9.0"
+
+[package.extras]
+docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
+qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
+testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
+
+[[package]]
+name = "jinja2"
+version = "3.0.3"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"},
+ {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "jsonalias"
+version = "0.1.1"
+description = "A microlibrary that defines a Json type alias for Python."
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "jsonalias-0.1.1-py3-none-any.whl", hash = "sha256:a56d2888e6397812c606156504e861e8ec00e188005af149f003c787db3d3f18"},
+ {file = "jsonalias-0.1.1.tar.gz", hash = "sha256:64f04d935397d579fc94509e1fcb6212f2d081235d9d6395bd10baedf760a769"},
+]
+
+[[package]]
+name = "jsonrpcclient"
+version = "4.0.3"
+description = "Send JSON-RPC requests"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "jsonrpcclient-4.0.3-py3-none-any.whl", hash = "sha256:3cbb9e27e1be29821becf135ea183144a836215422727e1ffe5056a49a670f0d"},
+]
+
+[package.extras]
+qa = ["pytest", "pytest-cov", "tox"]
+
+[[package]]
+name = "markdown"
+version = "3.3.7"
+description = "Python implementation of Markdown."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "Markdown-3.3.7-py3-none-any.whl", hash = "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621"},
+ {file = "Markdown-3.3.7.tar.gz", hash = "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874"},
+]
+
+[package.dependencies]
+importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""}
+
+[package.extras]
+testing = ["coverage", "pyyaml"]
+
+[[package]]
+name = "markupsafe"
+version = "2.1.2"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
+ {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
+]
+
+[[package]]
+name = "matplotlib-inline"
+version = "0.1.6"
+description = "Inline Matplotlib backend for Jupyter"
+optional = true
+python-versions = ">=3.5"
+files = [
+ {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"},
+ {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"},
+]
+
+[package.dependencies]
+traitlets = "*"
+
+[[package]]
+name = "mergedeep"
+version = "1.3.4"
+description = "A deep merge function for 🐍."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
+ {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
+]
+
+[[package]]
+name = "mkdocs"
+version = "1.4.3"
+description = "Project documentation with Markdown."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mkdocs-1.4.3-py3-none-any.whl", hash = "sha256:6ee46d309bda331aac915cd24aab882c179a933bd9e77b80ce7d2eaaa3f689dd"},
+ {file = "mkdocs-1.4.3.tar.gz", hash = "sha256:5955093bbd4dd2e9403c5afaf57324ad8b04f16886512a3ee6ef828956481c57"},
+]
+
+[package.dependencies]
+click = ">=7.0"
+colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""}
+ghp-import = ">=1.0"
+importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""}
+jinja2 = ">=2.11.1"
+markdown = ">=3.2.1,<3.4"
+mergedeep = ">=1.3.4"
+packaging = ">=20.5"
+pyyaml = ">=5.1"
+pyyaml-env-tag = ">=0.1"
+watchdog = ">=2.0"
+
+[package.extras]
+i18n = ["babel (>=2.9.0)"]
+min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"]
+
+[[package]]
+name = "mkdocs-autorefs"
+version = "0.4.1"
+description = "Automatically link across pages in MkDocs."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mkdocs-autorefs-0.4.1.tar.gz", hash = "sha256:70748a7bd025f9ecd6d6feeba8ba63f8e891a1af55f48e366d6d6e78493aba84"},
+ {file = "mkdocs_autorefs-0.4.1-py3-none-any.whl", hash = "sha256:a2248a9501b29dc0cc8ba4c09f4f47ff121945f6ce33d760f145d6f89d313f5b"},
+]
+
+[package.dependencies]
+Markdown = ">=3.3"
+mkdocs = ">=1.1"
+
+[[package]]
+name = "mkdocs-material"
+version = "8.5.11"
+description = "Documentation that simply works"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mkdocs_material-8.5.11-py3-none-any.whl", hash = "sha256:c907b4b052240a5778074a30a78f31a1f8ff82d7012356dc26898b97559f082e"},
+ {file = "mkdocs_material-8.5.11.tar.gz", hash = "sha256:b0ea0513fd8cab323e8a825d6692ea07fa83e917bb5db042e523afecc7064ab7"},
+]
+
+[package.dependencies]
+jinja2 = ">=3.0.2"
+markdown = ">=3.2"
+mkdocs = ">=1.4.0"
+mkdocs-material-extensions = ">=1.1"
+pygments = ">=2.12"
+pymdown-extensions = ">=9.4"
+requests = ">=2.26"
+
+[[package]]
+name = "mkdocs-material-extensions"
+version = "1.1.1"
+description = "Extension pack for Python Markdown and MkDocs Material."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mkdocs_material_extensions-1.1.1-py3-none-any.whl", hash = "sha256:e41d9f38e4798b6617ad98ca8f7f1157b1e4385ac1459ca1e4ea219b556df945"},
+ {file = "mkdocs_material_extensions-1.1.1.tar.gz", hash = "sha256:9c003da71e2cc2493d910237448c672e00cefc800d3d6ae93d2fc69979e3bd93"},
+]
+
+[[package]]
+name = "mkdocstrings"
+version = "0.17.0"
+description = "Automatic documentation from sources, for MkDocs."
+optional = false
+python-versions = ">=3.6.2"
+files = [
+ {file = "mkdocstrings-0.17.0-py3-none-any.whl", hash = "sha256:103fc1dd58cb23b7e0a6da5292435f01b29dc6fa0ba829132537f3f556f985de"},
+ {file = "mkdocstrings-0.17.0.tar.gz", hash = "sha256:75b5cfa2039aeaf3a5f5cf0aa438507b0330ce76c8478da149d692daa7213a98"},
+]
+
+[package.dependencies]
+Jinja2 = ">=2.11.1"
+Markdown = ">=3.3"
+MarkupSafe = ">=1.1"
+mkdocs = ">=1.2"
+mkdocs-autorefs = ">=0.1"
+pymdown-extensions = ">=6.3"
+pytkdocs = ">=0.14.0"
+
+[[package]]
+name = "more-itertools"
+version = "8.14.0"
+description = "More routines for operating on iterables, beyond itertools"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "more-itertools-8.14.0.tar.gz", hash = "sha256:c09443cd3d5438b8dafccd867a6bc1cb0894389e90cb53d227456b0b0bccb750"},
+ {file = "more_itertools-8.14.0-py3-none-any.whl", hash = "sha256:1bc4f91ee5b1b31ac7ceacc17c09befe6a40a503907baf9c839c229b5095cfd2"},
+]
+
+[[package]]
+name = "mypy"
+version = "0.982"
+description = "Optional static typing for Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"},
+ {file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"},
+ {file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"},
+ {file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"},
+ {file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"},
+ {file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"},
+ {file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"},
+ {file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"},
+ {file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"},
+ {file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"},
+ {file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"},
+ {file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"},
+ {file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"},
+ {file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"},
+ {file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"},
+ {file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"},
+ {file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"},
+ {file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"},
+ {file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"},
+ {file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"},
+ {file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"},
+ {file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"},
+ {file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"},
+ {file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"},
+]
+
+[package.dependencies]
+mypy-extensions = ">=0.4.3"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = ">=3.10"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+python2 = ["typed-ast (>=1.4.0,<2)"]
+reports = ["lxml"]
+
+[[package]]
+name = "mypy-extensions"
+version = "1.0.0"
+description = "Type system extensions for programs checked with the mypy type checker."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
+ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+]
+
+[[package]]
+name = "numpy"
+version = "1.24.3"
+description = "Fundamental package for array computing in Python"
+optional = true
+python-versions = ">=3.8"
+files = [
+ {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"},
+ {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"},
+ {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"},
+ {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"},
+ {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"},
+ {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"},
+ {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"},
+ {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"},
+ {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"},
+ {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"},
+ {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"},
+ {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"},
+ {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"},
+ {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"},
+ {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"},
+ {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"},
+ {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"},
+ {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"},
+ {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"},
+ {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"},
+ {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"},
+ {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"},
+ {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"},
+ {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"},
+ {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"},
+ {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"},
+ {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"},
+ {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"},
+]
+
+[[package]]
+name = "packaging"
+version = "23.1"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
+ {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
+]
+
+[[package]]
+name = "parso"
+version = "0.8.3"
+description = "A Python Parser"
+optional = true
+python-versions = ">=3.6"
+files = [
+ {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
+ {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
+]
+
+[package.extras]
+qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
+testing = ["docopt", "pytest (<6.0.0)"]
+
+[[package]]
+name = "pathspec"
+version = "0.11.1"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = true
+python-versions = ">=3.7"
+files = [
+ {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
+ {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
+]
+
+[[package]]
+name = "pexpect"
+version = "4.8.0"
+description = "Pexpect allows easy control of interactive console applications."
+optional = true
+python-versions = "*"
+files = [
+ {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
+ {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"},
+]
+
+[package.dependencies]
+ptyprocess = ">=0.5"
+
+[[package]]
+name = "pickleshare"
+version = "0.7.5"
+description = "Tiny 'shelve'-like database with concurrency support"
+optional = true
+python-versions = "*"
+files = [
+ {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"},
+ {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
+]
+
+[[package]]
+name = "platformdirs"
+version = "3.5.1"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+optional = true
+python-versions = ">=3.7"
+files = [
+ {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"},
+ {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"},
+]
+
+[package.extras]
+docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
+
+[[package]]
+name = "pluggy"
+version = "1.0.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "prompt-toolkit"
+version = "3.0.38"
+description = "Library for building powerful interactive command lines in Python"
+optional = true
+python-versions = ">=3.7.0"
+files = [
+ {file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"},
+ {file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"},
+]
+
+[package.dependencies]
+wcwidth = "*"
+
+[[package]]
+name = "psutil"
+version = "5.9.5"
+description = "Cross-platform lib for process and system monitoring in Python."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"},
+ {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"},
+ {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"},
+ {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"},
+ {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"},
+ {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"},
+ {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"},
+ {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"},
+ {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"},
+ {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"},
+ {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"},
+ {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"},
+ {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"},
+ {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"},
+]
+
+[package.extras]
+test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
+
+[[package]]
+name = "ptyprocess"
+version = "0.7.0"
+description = "Run a subprocess in a pseudo terminal"
+optional = true
+python-versions = "*"
+files = [
+ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
+ {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
+]
+
+[[package]]
+name = "pure-eval"
+version = "0.2.2"
+description = "Safely evaluate AST nodes without side effects"
+optional = true
+python-versions = "*"
+files = [
+ {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"},
+ {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"},
+]
+
+[package.extras]
+tests = ["pytest"]
+
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+
+[[package]]
+name = "pycparser"
+version = "2.21"
+description = "C parser in Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
+ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
+]
+
+[[package]]
+name = "pyflakes"
+version = "2.5.0"
+description = "passive checker of Python programs"
+optional = true
+python-versions = ">=3.6"
+files = [
+ {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"},
+ {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"},
+]
+
+[[package]]
+name = "pygments"
+version = "2.15.1"
+description = "Pygments is a syntax highlighting package written in Python."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
+ {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
+]
+
+[package.extras]
+plugins = ["importlib-metadata"]
+
+[[package]]
+name = "pyheck"
+version = "0.1.5"
+description = "Python bindings for heck, the Rust case conversion library"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pyheck-0.1.5-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:44caf2b7a49d71fdeb0469e9f35886987ad815a8638b3c5b5c83f351d6aed413"},
+ {file = "pyheck-0.1.5-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:316a842b94beff6e59a97dbcc590e9be92a932e59126b0faa9ac750384f27eaf"},
+ {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b6169397395ff041f056bfb36c1957a788a1cd7cb967a927fcae7917ff1b6aa"},
+ {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e9d101e1c599227280e34eeccab0414246e70a91a1cabb4c4868dca284f2be7d"},
+ {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:69d6509138909df92b2f2f837518dca118ef08ae3c804044ae511b81b7aecb4d"},
+ {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ce4a2e1b4778051b8f31183e321a034603f3957b6e95cf03bf5f231c8ea3066"},
+ {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69387b70d910637ab6dc8dc378c8e0b4037cee2c51a9c6f64ce5331b010f5de3"},
+ {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0fb50b7d899d2a583ec2ac291b8ec2afb10f0e32c4ac290148d3da15927787f8"},
+ {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:aa8dfd0883212f8495e0bae6eb6ea670c56f9b197b5fe6fb5cae9fd5ec56fb7c"},
+ {file = "pyheck-0.1.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b7c07506b9591e27f8241bf7a72bc4d5c4ac30dedb332efb87e402e49029f233"},
+ {file = "pyheck-0.1.5-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:9ee256cafbdab6c5fcca22d0910176d820bf1e1298773e64f4eea79f51218cc7"},
+ {file = "pyheck-0.1.5-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:e9ba36060abc55127c3813de398b4013c05be6118cfae3cfa3d978f7b4c84dea"},
+ {file = "pyheck-0.1.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:64201a6d213bec443aeb33f66c60cea61aaf6257e48a19159ac69a5afad4768e"},
+ {file = "pyheck-0.1.5-cp37-abi3-win32.whl", hash = "sha256:1501fcfd15f7c05c6bfe38915f5e514ac95fc63e945f7d8b089d30c1b8fdb2c5"},
+ {file = "pyheck-0.1.5-cp37-abi3-win_amd64.whl", hash = "sha256:e519f80a0ef87a8f880bfdf239e396e238dcaed34bec1ea7ef526c4873220e82"},
+ {file = "pyheck-0.1.5.tar.gz", hash = "sha256:5c9fe372d540c5dbcb76bf062f951d998d0e14c906c842a52f1cd5de208e183a"},
+]
+
+[[package]]
+name = "pymdown-extensions"
+version = "10.0.1"
+description = "Extension pack for Python Markdown."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pymdown_extensions-10.0.1-py3-none-any.whl", hash = "sha256:ae66d84013c5d027ce055693e09a4628b67e9dec5bce05727e45b0918e36f274"},
+ {file = "pymdown_extensions-10.0.1.tar.gz", hash = "sha256:b44e1093a43b8a975eae17b03c3a77aad4681b3b56fce60ce746dbef1944c8cb"},
+]
+
+[package.dependencies]
+markdown = ">=3.2"
+pyyaml = "*"
+
+[[package]]
+name = "pytest"
+version = "7.3.1"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
+ {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+
+[[package]]
+name = "pytest-asyncio"
+version = "0.21.0"
+description = "Pytest support for asyncio"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-asyncio-0.21.0.tar.gz", hash = "sha256:2b38a496aef56f56b0e87557ec313e11e1ab9276fc3863f6a7be0f1d0e415e1b"},
+ {file = "pytest_asyncio-0.21.0-py3-none-any.whl", hash = "sha256:f2b3366b7cd501a4056858bd39349d5af19742aed2d81660b7998b6341c7eb9c"},
+]
+
+[package.dependencies]
+pytest = ">=7.0.0"
+
+[package.extras]
+docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
+testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
+
+[[package]]
+name = "pytest-xprocess"
+version = "0.18.1"
+description = "A pytest plugin for managing processes across test runs."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "pytest-xprocess-0.18.1.tar.gz", hash = "sha256:fd9f30ed1584b5833bc34494748adf0fb9de3ca7bacc4e88ad71989c21cba266"},
+ {file = "pytest_xprocess-0.18.1-py3-none-any.whl", hash = "sha256:6f2aba817d842518d9d9dfb7e9adfe2a6e354a4359f4166bef0822ef4be1c9db"},
+]
+
+[package.dependencies]
+psutil = "*"
+pytest = ">=2.8"
+
+[[package]]
+name = "python-dateutil"
+version = "2.8.2"
+description = "Extensions to the standard Python datetime module"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+files = [
+ {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
+ {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
+]
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+name = "pytkdocs"
+version = "0.16.1"
+description = "Load Python objects documentation."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytkdocs-0.16.1-py3-none-any.whl", hash = "sha256:a8c3f46ecef0b92864cc598e9101e9c4cf832ebbf228f50c84aa5dd850aac379"},
+ {file = "pytkdocs-0.16.1.tar.gz", hash = "sha256:e2ccf6dfe9dbbceb09818673f040f1a7c32ed0bffb2d709b06be6453c4026045"},
+]
+
+[package.extras]
+numpy-style = ["docstring_parser (>=0.7)"]
+
+[[package]]
+name = "pytools"
+version = "2022.1.14"
+description = "A collection of tools for Python"
+optional = true
+python-versions = "~=3.8"
+files = [
+ {file = "pytools-2022.1.14.tar.gz", hash = "sha256:41017371610bb2a03685597c5285205e6597c7f177383d95c8b871244b12c14e"},
+]
+
+[package.dependencies]
+platformdirs = ">=2.2.0"
+typing_extensions = {version = ">=4.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+numpy = ["numpy (>=1.6.0)"]
+
+[[package]]
+name = "pyyaml"
+version = "6.0"
+description = "YAML parser and emitter for Python"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
+ {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
+ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
+ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
+ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
+ {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
+ {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
+ {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
+ {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
+ {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
+ {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
+ {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
+ {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
+ {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
+ {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
+ {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
+ {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
+ {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
+ {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
+ {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
+ {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
+ {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
+ {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
+ {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
+ {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
+ {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
+ {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
+ {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
+ {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
+ {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
+ {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
+ {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
+ {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
+ {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
+ {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
+ {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
+ {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
+ {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
+ {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
+ {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
+]
+
+[[package]]
+name = "pyyaml-env-tag"
+version = "0.1"
+description = "A custom YAML tag for referencing environment variables in YAML files. "
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
+ {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
+]
+
+[package.dependencies]
+pyyaml = "*"
+
+[[package]]
+name = "requests"
+version = "2.31.0"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
+ {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "rfc3986"
+version = "1.5.0"
+description = "Validating URI References per RFC 3986"
+optional = false
+python-versions = "*"
+files = [
+ {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"},
+ {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"},
+]
+
+[package.dependencies]
+idna = {version = "*", optional = true, markers = "extra == \"idna2008\""}
+
+[package.extras]
+idna2008 = ["idna"]
+
+[[package]]
+name = "ruff"
+version = "0.0.220"
+description = "An extremely fast Python linter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff-0.0.220-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:152e6697aca6aea991cdd37922c34a3e4db4828822c4663122326e6051e0f68a"},
+ {file = "ruff-0.0.220-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:127887a00d53beb7c0c78a8b4bbdda2f14f07db7b3571feb6855cb32862cb88d"},
+ {file = "ruff-0.0.220-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91235ff448786f8f3b856c104fd6c4fe11e835b0db75da5fdf337e1ed5d454da"},
+ {file = "ruff-0.0.220-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f0a104afc32012048627317ae8b0940e3f11a717905aed3fc26931a873e3b29"},
+ {file = "ruff-0.0.220-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eee1deddf1671860e056a78938176600108857a527c078038627b284a554723c"},
+ {file = "ruff-0.0.220-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:071082d09c953924eccfd88ffd0d71119ddd6fc7767f3c31549a1cd0651ba586"},
+ {file = "ruff-0.0.220-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5ddfc945a9076c9779b52c1f7296cf8d8e6919e619c4522617bc37b60eddd2e"},
+ {file = "ruff-0.0.220-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15f387fd156430353fb61d2b609f1c38d2e9096e2fce31149da5cf08b73f04a8"},
+ {file = "ruff-0.0.220-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5688983f21ac64bbcca8d84f4107733cc2d62c1354ea1a6b85eb9ead32328cc"},
+ {file = "ruff-0.0.220-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e2b0c9dbff13649ded5ee92d6a47d720e8471461e0a4eba01bf3474f851cb2f0"},
+ {file = "ruff-0.0.220-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9b540fa9f90f46f656b34fb73b738613562974599903a1f0d40bdd1a8180bfab"},
+ {file = "ruff-0.0.220-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a061c17c2b0f81193fca5e53829b6c0569c5c7d393cc4fc1c192ce0a64d3b9ca"},
+ {file = "ruff-0.0.220-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:42677089abd7db6f8aefa3dbe7a82fea4e2a43a08bc7bf6d3f58ec3d76c63712"},
+ {file = "ruff-0.0.220-py3-none-win32.whl", hash = "sha256:f8821cfc204b38140afe870bcd4cc6c836bbd2f820b92df66b8fe8b8d71a3772"},
+ {file = "ruff-0.0.220-py3-none-win_amd64.whl", hash = "sha256:8a1d678a224afd7149afbe497c97c3ccdc6c42632ee84fb0e3f68d190c1ccec1"},
+ {file = "ruff-0.0.220.tar.gz", hash = "sha256:621f7f063c0d13570b709fb9904a329ddb9a614fdafc786718afd43e97440c34"},
+]
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+
+[[package]]
+name = "sniffio"
+version = "1.3.0"
+description = "Sniff out which async library your code is running under"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"},
+ {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"},
+]
+
+[[package]]
+name = "solana"
+version = "0.30.2"
+description = "Solana Python API"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "solana-0.30.2-py3-none-any.whl", hash = "sha256:d7e8295a1f86982ba51e78a65c16ce55f4a9e9caa8938564922a209ddfb2a01f"},
+ {file = "solana-0.30.2.tar.gz", hash = "sha256:7b16e76cdd1d3024219679cdb73c20324d6d79e3c9766fe0ca52be79ef5ff691"},
+]
+
+[package.dependencies]
+cachetools = ">=4.2.2,<5.0.0"
+construct-typing = ">=0.5.2,<0.6.0"
+httpx = ">=0.23.0,<0.24.0"
+solders = ">=0.18.0,<0.19.0"
+types-cachetools = ">=4.2.4,<5.0.0"
+typing-extensions = ">=4.2.0"
+websockets = ">=9.0,<12.0"
+
+[[package]]
+name = "solders"
+version = "0.18.0"
+description = "Python bindings for Solana Rust tools"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "solders-0.18.0-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:cd30c9a2b1967975b2d05895cc4a3ef701c9e686a1d156e131a6c97d4b1decd5"},
+ {file = "solders-0.18.0-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b7c9cafffa570652aaabf5d3ccc987ea18c9470718631e4881ca679823b18ae"},
+ {file = "solders-0.18.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90be96a432d8580ff52eed6098b4be12c064829588304f8f2a79d9adfd2b789d"},
+ {file = "solders-0.18.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07c700ad784754609cffe2fd4177124c359d5353ba1d2d8b6d4e8ae59957aa7d"},
+ {file = "solders-0.18.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a29449f6827d2a220bed2873f4a485f000e01ddc9f58ba19771c5d53fa4fe28d"},
+ {file = "solders-0.18.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:3260b9d3c469818d9229a667621b4714863fa35ca2709a1c6e224efc21e516cc"},
+ {file = "solders-0.18.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:632ba10040d3fac819363abb3cbbd3a5974e8c9800b897ca9641efe9b36b4975"},
+ {file = "solders-0.18.0-cp37-abi3-win_amd64.whl", hash = "sha256:40cc86dccee766c05ccd594a66761b44248907bfbfa85956bbbc9fb504dde7cd"},
+ {file = "solders-0.18.0.tar.gz", hash = "sha256:8c32aa7c3a0fa87a2f4589279ce70b17261096bae09316ca4a4e1052f471c629"},
+]
+
+[package.dependencies]
+jsonalias = "0.1.1"
+typing-extensions = ">=4.2.0"
+
+[[package]]
+name = "stack-data"
+version = "0.6.2"
+description = "Extract data from python stack frames and tracebacks for informative displays"
+optional = true
+python-versions = "*"
+files = [
+ {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"},
+ {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"},
+]
+
+[package.dependencies]
+asttokens = ">=2.1.0"
+executing = ">=1.2.0"
+pure-eval = "*"
+
+[package.extras]
+tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
+
+[[package]]
+name = "sumtypes"
+version = "0.1a6"
+description = "Algebraic types for Python (notably providing Sum Types, aka Tagged Unions)"
+optional = false
+python-versions = "*"
+files = [
+ {file = "sumtypes-0.1a6-py2.py3-none-any.whl", hash = "sha256:3e9d71322dd927d25d935072f8be7daec655ea292fd392359a5bb2c1e53dfdc3"},
+ {file = "sumtypes-0.1a6.tar.gz", hash = "sha256:1a6ff095e06a1885f340ddab803e0f38e3f9bed81f9090164ca9682e04e96b43"},
+]
+
+[package.dependencies]
+attrs = "*"
+
+[[package]]
+name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
+]
+
+[[package]]
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+
+[[package]]
+name = "toolz"
+version = "0.11.2"
+description = "List processing tools and functional utilities"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "toolz-0.11.2-py3-none-any.whl", hash = "sha256:a5700ce83414c64514d82d60bcda8aabfde092d1c1a8663f9200c07fdcc6da8f"},
+ {file = "toolz-0.11.2.tar.gz", hash = "sha256:6b312d5e15138552f1bda8a4e66c30e236c831b612b2bf0005f8a1df10a4bc33"},
+]
+
+[[package]]
+name = "traitlets"
+version = "5.9.0"
+description = "Traitlets Python configuration system"
+optional = true
+python-versions = ">=3.7"
+files = [
+ {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"},
+ {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"},
+]
+
+[package.extras]
+docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"]
+test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"]
+
+[[package]]
+name = "typer"
+version = "0.4.1"
+description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
+optional = true
+python-versions = ">=3.6"
+files = [
+ {file = "typer-0.4.1-py3-none-any.whl", hash = "sha256:e8467f0ebac0c81366c2168d6ad9f888efdfb6d4e1d3d5b4a004f46fa444b5c3"},
+ {file = "typer-0.4.1.tar.gz", hash = "sha256:5646aef0d936b2c761a10393f0384ee6b5c7fe0bb3e5cd710b17134ca1d99cff"},
+]
+
+[package.dependencies]
+click = ">=7.1.1,<9.0.0"
+
+[package.extras]
+all = ["colorama (>=0.4.3,<0.5.0)", "shellingham (>=1.3.0,<2.0.0)"]
+dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)"]
+doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)"]
+test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+
+[[package]]
+name = "types-cachetools"
+version = "4.2.10"
+description = "Typing stubs for cachetools"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-cachetools-4.2.10.tar.gz", hash = "sha256:b1cb18aaff25d2ad47a060413c660c39fadddb01f72012dd1134584b1fdaada5"},
+ {file = "types_cachetools-4.2.10-py3-none-any.whl", hash = "sha256:48301115189d4879d0960baac5a8a2b2d31ce6129b2ce3b915000ed337284898"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.6.3"
+description = "Backported and Experimental Type Hints for Python 3.7+"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"},
+ {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"},
+]
+
+[[package]]
+name = "urllib3"
+version = "2.0.2"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"},
+ {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[[package]]
+name = "watchdog"
+version = "3.0.0"
+description = "Filesystem events monitoring"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"},
+ {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"},
+ {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"},
+ {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"},
+ {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"},
+ {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"},
+ {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"},
+ {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"},
+ {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"},
+ {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"},
+ {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"},
+ {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"},
+ {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"},
+ {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"},
+ {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"},
+ {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"},
+ {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"},
+ {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"},
+ {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"},
+ {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"},
+ {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"},
+ {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"},
+ {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"},
+ {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"},
+ {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"},
+ {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"},
+ {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"},
+]
+
+[package.extras]
+watchmedo = ["PyYAML (>=3.10)"]
+
+[[package]]
+name = "wcwidth"
+version = "0.2.6"
+description = "Measures the displayed width of unicode strings in a terminal"
+optional = true
+python-versions = "*"
+files = [
+ {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"},
+ {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"},
+]
+
+[[package]]
+name = "websockets"
+version = "10.4"
+description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "websockets-10.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48"},
+ {file = "websockets-10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc0b82d728fe21a0d03e65f81980abbbcb13b5387f733a1a870672c5be26edab"},
+ {file = "websockets-10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba089c499e1f4155d2a3c2a05d2878a3428cf321c848f2b5a45ce55f0d7d310c"},
+ {file = "websockets-10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d69ca7612f0ddff3316b0c7b33ca180d464ecac2d115805c044bf0a3b0d032"},
+ {file = "websockets-10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e627f6b6d4aed919a2052efc408da7a545c606268d5ab5bfab4432734b82b4"},
+ {file = "websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ea7b82bfcae927eeffc55d2ffa31665dc7fec7b8dc654506b8e5a518eb4d50"},
+ {file = "websockets-10.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e0cb5cc6ece6ffa75baccfd5c02cffe776f3f5c8bf486811f9d3ea3453676ce8"},
+ {file = "websockets-10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae5e95cfb53ab1da62185e23b3130e11d64431179debac6dc3c6acf08760e9b1"},
+ {file = "websockets-10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7c584f366f46ba667cfa66020344886cf47088e79c9b9d39c84ce9ea98aaa331"},
+ {file = "websockets-10.4-cp310-cp310-win32.whl", hash = "sha256:b029fb2032ae4724d8ae8d4f6b363f2cc39e4c7b12454df8df7f0f563ed3e61a"},
+ {file = "websockets-10.4-cp310-cp310-win_amd64.whl", hash = "sha256:8dc96f64ae43dde92530775e9cb169979f414dcf5cff670455d81a6823b42089"},
+ {file = "websockets-10.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:47a2964021f2110116cc1125b3e6d87ab5ad16dea161949e7244ec583b905bb4"},
+ {file = "websockets-10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e789376b52c295c4946403bd0efecf27ab98f05319df4583d3c48e43c7342c2f"},
+ {file = "websockets-10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3f0b61c45c3fa9a349cf484962c559a8a1d80dae6977276df8fd1fa5e3cb8c"},
+ {file = "websockets-10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55b5905705725af31ccef50e55391621532cd64fbf0bc6f4bac935f0fccec46"},
+ {file = "websockets-10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00c870522cdb69cd625b93f002961ffb0c095394f06ba8c48f17eef7c1541f96"},
+ {file = "websockets-10.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f38706e0b15d3c20ef6259fd4bc1700cd133b06c3c1bb108ffe3f8947be15fa"},
+ {file = "websockets-10.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f2c38d588887a609191d30e902df2a32711f708abfd85d318ca9b367258cfd0c"},
+ {file = "websockets-10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fe10ddc59b304cb19a1bdf5bd0a7719cbbc9fbdd57ac80ed436b709fcf889106"},
+ {file = "websockets-10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90fcf8929836d4a0e964d799a58823547df5a5e9afa83081761630553be731f9"},
+ {file = "websockets-10.4-cp311-cp311-win32.whl", hash = "sha256:b9968694c5f467bf67ef97ae7ad4d56d14be2751000c1207d31bf3bb8860bae8"},
+ {file = "websockets-10.4-cp311-cp311-win_amd64.whl", hash = "sha256:a7a240d7a74bf8d5cb3bfe6be7f21697a28ec4b1a437607bae08ac7acf5b4882"},
+ {file = "websockets-10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74de2b894b47f1d21cbd0b37a5e2b2392ad95d17ae983e64727e18eb281fe7cb"},
+ {file = "websockets-10.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3a686ecb4aa0d64ae60c9c9f1a7d5d46cab9bfb5d91a2d303d00e2cd4c4c5cc"},
+ {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d15c968ea7a65211e084f523151dbf8ae44634de03c801b8bd070b74e85033"},
+ {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41"},
+ {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e23173580d740bf8822fd0379e4bf30aa1d5a92a4f252d34e893070c081050df"},
+ {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:dd500e0a5e11969cdd3320935ca2ff1e936f2358f9c2e61f100a1660933320ea"},
+ {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4239b6027e3d66a89446908ff3027d2737afc1a375f8fd3eea630a4842ec9a0c"},
+ {file = "websockets-10.4-cp37-cp37m-win32.whl", hash = "sha256:8a5cc00546e0a701da4639aa0bbcb0ae2bb678c87f46da01ac2d789e1f2d2038"},
+ {file = "websockets-10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:a9f9a735deaf9a0cadc2d8c50d1a5bcdbae8b6e539c6e08237bc4082d7c13f28"},
+ {file = "websockets-10.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c1289596042fad2cdceb05e1ebf7aadf9995c928e0da2b7a4e99494953b1b94"},
+ {file = "websockets-10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0cff816f51fb33c26d6e2b16b5c7d48eaa31dae5488ace6aae468b361f422b63"},
+ {file = "websockets-10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dd9becd5fe29773d140d68d607d66a38f60e31b86df75332703757ee645b6faf"},
+ {file = "websockets-10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45ec8e75b7dbc9539cbfafa570742fe4f676eb8b0d3694b67dabe2f2ceed8aa6"},
+ {file = "websockets-10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f72e5cd0f18f262f5da20efa9e241699e0cf3a766317a17392550c9ad7b37d8"},
+ {file = "websockets-10.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185929b4808b36a79c65b7865783b87b6841e852ef5407a2fb0c03381092fa3b"},
+ {file = "websockets-10.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d27a7e34c313b3a7f91adcd05134315002aaf8540d7b4f90336beafaea6217c"},
+ {file = "websockets-10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:884be66c76a444c59f801ac13f40c76f176f1bfa815ef5b8ed44321e74f1600b"},
+ {file = "websockets-10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:931c039af54fc195fe6ad536fde4b0de04da9d5916e78e55405436348cfb0e56"},
+ {file = "websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"},
+ {file = "websockets-10.4-cp38-cp38-win_amd64.whl", hash = "sha256:48c08473563323f9c9debac781ecf66f94ad5a3680a38fe84dee5388cf5acaf6"},
+ {file = "websockets-10.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:40e826de3085721dabc7cf9bfd41682dadc02286d8cf149b3ad05bff89311e4f"},
+ {file = "websockets-10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56029457f219ade1f2fc12a6504ea61e14ee227a815531f9738e41203a429112"},
+ {file = "websockets-10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5fc088b7a32f244c519a048c170f14cf2251b849ef0e20cbbb0fdf0fdaf556f"},
+ {file = "websockets-10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc8709c00704194213d45e455adc106ff9e87658297f72d544220e32029cd3d"},
+ {file = "websockets-10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0154f7691e4fe6c2b2bc275b5701e8b158dae92a1ab229e2b940efe11905dff4"},
+ {file = "websockets-10.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c6d2264f485f0b53adf22697ac11e261ce84805c232ed5dbe6b1bcb84b00ff0"},
+ {file = "websockets-10.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9bc42e8402dc5e9905fb8b9649f57efcb2056693b7e88faa8fb029256ba9c68c"},
+ {file = "websockets-10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:edc344de4dac1d89300a053ac973299e82d3db56330f3494905643bb68801269"},
+ {file = "websockets-10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:84bc2a7d075f32f6ed98652db3a680a17a4edb21ca7f80fe42e38753a58ee02b"},
+ {file = "websockets-10.4-cp39-cp39-win32.whl", hash = "sha256:c94ae4faf2d09f7c81847c63843f84fe47bf6253c9d60b20f25edfd30fb12588"},
+ {file = "websockets-10.4-cp39-cp39-win_amd64.whl", hash = "sha256:bbccd847aa0c3a69b5f691a84d2341a4f8a629c6922558f2a70611305f902d74"},
+ {file = "websockets-10.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:82ff5e1cae4e855147fd57a2863376ed7454134c2bf49ec604dfe71e446e2193"},
+ {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d210abe51b5da0ffdbf7b43eed0cfdff8a55a1ab17abbec4301c9ff077dd0342"},
+ {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:942de28af58f352a6f588bc72490ae0f4ccd6dfc2bd3de5945b882a078e4e179"},
+ {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b27d6c1c6cd53dc93614967e9ce00ae7f864a2d9f99fe5ed86706e1ecbf485"},
+ {file = "websockets-10.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3d3cac3e32b2c8414f4f87c1b2ab686fa6284a980ba283617404377cd448f631"},
+ {file = "websockets-10.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:da39dd03d130162deb63da51f6e66ed73032ae62e74aaccc4236e30edccddbb0"},
+ {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389f8dbb5c489e305fb113ca1b6bdcdaa130923f77485db5b189de343a179393"},
+ {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09a1814bb15eff7069e51fed0826df0bc0702652b5cb8f87697d469d79c23576"},
+ {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff64a1d38d156d429404aaa84b27305e957fd10c30e5880d1765c9480bea490f"},
+ {file = "websockets-10.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b343f521b047493dc4022dd338fc6db9d9282658862756b4f6fd0e996c1380e1"},
+ {file = "websockets-10.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:932af322458da7e4e35df32f050389e13d3d96b09d274b22a7aa1808f292fee4"},
+ {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a4162139374a49eb18ef5b2f4da1dd95c994588f5033d64e0bbfda4b6b6fcf"},
+ {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c57e4c1349fbe0e446c9fa7b19ed2f8a4417233b6984277cce392819123142d3"},
+ {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b627c266f295de9dea86bd1112ed3d5fafb69a348af30a2422e16590a8ecba13"},
+ {file = "websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"},
+ {file = "websockets-10.4.tar.gz", hash = "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"},
+]
+
+[[package]]
+name = "zipp"
+version = "3.15.0"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
+ {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+
+[[package]]
+name = "zstandard"
+version = "0.18.0"
+description = "Zstandard bindings for Python"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "zstandard-0.18.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef7e8a200e4c8ac9102ed3c90ed2aa379f6b880f63032200909c1be21951f556"},
+ {file = "zstandard-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2dc466207016564805e56d28375f4f533b525ff50d6776946980dff5465566ac"},
+ {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a2ee1d4f98447f3e5183ecfce5626f983504a4a0c005fbe92e60fa8e5d547ec"},
+ {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d956e2f03c7200d7e61345e0880c292783ec26618d0d921dcad470cb195bbce2"},
+ {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ce6f59cba9854fd14da5bfe34217a1501143057313966637b7291d1b0267bd1e"},
+ {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fa67cba473623848b6e88acf8d799b1906178fd883fb3a1da24561c779593b"},
+ {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdb44d7284c8c5dd1b66dfb86dda7f4560fa94bfbbc1d2da749ba44831335e32"},
+ {file = "zstandard-0.18.0-cp310-cp310-win32.whl", hash = "sha256:63694a376cde0aa8b1971d06ca28e8f8b5f492779cb6ee1cc46bbc3f019a42a5"},
+ {file = "zstandard-0.18.0-cp310-cp310-win_amd64.whl", hash = "sha256:702a8324cd90c74d9c8780d02bf55e79da3193c870c9665ad3a11647e3ad1435"},
+ {file = "zstandard-0.18.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46f679bc5dfd938db4fb058218d9dc4db1336ffaf1ea774ff152ecadabd40805"},
+ {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc2a4de9f363b3247d472362a65041fe4c0f59e01a2846b15d13046be866a885"},
+ {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd3220d7627fd4d26397211cb3b560ec7cc4a94b75cfce89e847e8ce7fabe32d"},
+ {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:39e98cf4773234bd9cebf9f9db730e451dfcfe435e220f8921242afda8321887"},
+ {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5228e596eb1554598c872a337bbe4e5afe41cd1f8b1b15f2e35b50d061e35244"},
+ {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d4a8fd45746a6c31e729f35196e80b8f1e9987c59f5ccb8859d7c6a6fbeb9c63"},
+ {file = "zstandard-0.18.0-cp36-cp36m-win32.whl", hash = "sha256:4cbb85f29a990c2fdbf7bc63246567061a362ddca886d7fae6f780267c0a9e67"},
+ {file = "zstandard-0.18.0-cp36-cp36m-win_amd64.whl", hash = "sha256:bfa6c8549fa18e6497a738b7033c49f94a8e2e30c5fbe2d14d0b5aa8bbc1695d"},
+ {file = "zstandard-0.18.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e02043297c1832f2666cd2204f381bef43b10d56929e13c42c10c732c6e3b4ed"},
+ {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7231543d38d2b7e02ef7cc78ef7ffd86419437e1114ff08709fe25a160e24bd6"},
+ {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c86befac87445927488f5c8f205d11566f64c11519db223e9d282b945fa60dab"},
+ {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:999a4e1768f219826ba3fa2064fab1c86dd72fdd47a42536235478c3bb3ca3e2"},
+ {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9df59cd1cf3c62075ee2a4da767089d19d874ac3ad42b04a71a167e91b384722"},
+ {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1be31e9e3f7607ee0cdd60915410a5968b205d3e7aa83b7fcf3dd76dbbdb39e0"},
+ {file = "zstandard-0.18.0-cp37-cp37m-win32.whl", hash = "sha256:490d11b705b8ae9dc845431bacc8dd1cef2408aede176620a5cd0cd411027936"},
+ {file = "zstandard-0.18.0-cp37-cp37m-win_amd64.whl", hash = "sha256:266aba27fa9cc5e9091d3d325ebab1fa260f64e83e42516d5e73947c70216a5b"},
+ {file = "zstandard-0.18.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8b2260c4e07dd0723eadb586de7718b61acca4083a490dda69c5719d79bc715c"},
+ {file = "zstandard-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3af8c2383d02feb6650e9255491ec7d0824f6e6dd2bbe3e521c469c985f31fb1"},
+ {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28723a1d2e4df778573b76b321ebe9f3469ac98988104c2af116dd344802c3f8"},
+ {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19cac7108ff2c342317fad6dc97604b47a41f403c8f19d0bfc396dfadc3638b8"},
+ {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:76725d1ee83a8915100a310bbad5d9c1fc6397410259c94033b8318d548d9990"},
+ {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d716a7694ce1fa60b20bc10f35c4a22be446ef7f514c8dbc8f858b61976de2fb"},
+ {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:49685bf9a55d1ab34bd8423ea22db836ba43a181ac6b045ac4272093d5cb874e"},
+ {file = "zstandard-0.18.0-cp38-cp38-win32.whl", hash = "sha256:1af1268a7dc870eb27515fb8db1f3e6c5a555d2b7bcc476fc3bab8886c7265ab"},
+ {file = "zstandard-0.18.0-cp38-cp38-win_amd64.whl", hash = "sha256:1dc2d3809e763055a1a6c1a73f2b677320cc9a5aa1a7c6cfb35aee59bddc42d9"},
+ {file = "zstandard-0.18.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eea18c1e7442f2aa9aff1bb84550dbb6a1f711faf6e48e7319de8f2b2e923c2a"},
+ {file = "zstandard-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8677ffc6a6096cccbd892e558471c901fd821aba12b7fbc63833c7346f549224"},
+ {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083dc08abf03807af9beeb2b6a91c23ad78add2499f828176a3c7b742c44df02"},
+ {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c990063664c08169c84474acecc9251ee035871589025cac47c060ff4ec4bc1a"},
+ {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:533db8a6fac6248b2cb2c935e7b92f994efbdeb72e1ffa0b354432e087bb5a3e"},
+ {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb3cb8a082d62b8a73af42291569d266b05605e017a3d8a06a0e5c30b5f10f0"},
+ {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d6c85ca5162049ede475b7ec98e87f9390501d44a3d6776ddd504e872464ec25"},
+ {file = "zstandard-0.18.0-cp39-cp39-win32.whl", hash = "sha256:75479e7c2b3eebf402c59fbe57d21bc400cefa145ca356ee053b0a08908c5784"},
+ {file = "zstandard-0.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:d85bfabad444812133a92fc6fbe463e1d07581dba72f041f07a360e63808b23c"},
+ {file = "zstandard-0.18.0.tar.gz", hash = "sha256:0ac0357a0d985b4ff31a854744040d7b5754385d1f98f7145c30e02c6865cb6f"},
+]
+
+[package.dependencies]
+cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\""}
+
+[package.extras]
+cffi = ["cffi (>=1.11)"]
+
+[extras]
+cli = ["autoflake", "black", "genpy", "ipython", "typer"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.9"
+content-hash = "1ef0fbc00af0df7e4455594d7934825823269276e8bc9efd2af9e2fc8ddd50f2"
diff --git a/basics/anchorpy-main/poetry.toml b/basics/anchorpy-main/poetry.toml
new file mode 100644
index 0000000..ab1033b
--- /dev/null
+++ b/basics/anchorpy-main/poetry.toml
@@ -0,0 +1,2 @@
+[virtualenvs]
+in-project = true
diff --git a/basics/anchorpy-main/pyproject.toml b/basics/anchorpy-main/pyproject.toml
new file mode 100644
index 0000000..5b20620
--- /dev/null
+++ b/basics/anchorpy-main/pyproject.toml
@@ -0,0 +1,118 @@
+[tool.poetry]
+name = "anchorpy"
+version = "0.18.0"
+description = "The Python Anchor client."
+readme = "README.md"
+repository = "https://github.com/kevinheavey/anchorpy"
+documentation = "https://kevinheavey.github.io/anchorpy/"
+authors = ["kevinheavey "]
+
+[tool.poetry.dependencies]
+python = "^3.9"
+construct-typing = "^0.5.1"
+solana = "^0.30.2"
+solders = "^0.18.0"
+borsh-construct = "^0.1.0"
+websockets = ">=9.0,<11.0"
+toolz = "^0.11.2"
+jsonrpcclient = "^4.0.1"
+zstandard = "^0.18.0"
+pytest = "^7.2.0"
+pytest-xprocess = "^0.18.1"
+pytest-asyncio = "^0.21.0"
+more-itertools = "^8.11.0"
+pyheck = "^0.1.4"
+typer = { version = "0.4.1", optional = true }
+ipython = { version = "^8.0.1", optional = true }
+genpy = { version = "^2021.1", optional = true }
+black = { version = "^22.3.0", optional = true }
+autoflake = { version = "^1.4", optional = true }
+based58 = "^0.1.1"
+anchorpy-core = "^0.1.3"
+py = "^1.11.0"
+toml = "^0.10.2"
+
+[tool.poetry.extras]
+cli = ["typer", "ipython", "genpy", "black", "autoflake"]
+
+
+[tool.poetry.scripts]
+anchorpy = "anchorpy.cli:app"
+
+[tool.poetry.dev-dependencies]
+mypy = "^0.982"
+jinja2 = "3.0.3"
+mkdocs-material = "^8.1.7"
+bump2version = "^1.0.1"
+mkdocstrings = "^0.17.0"
+ruff = "^0.0.220"
+
+[tool.poetry.plugins.pytest11]
+pytest_anchorpy = "anchorpy.pytest_plugin"
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.ruff]
+select = [
+ "A",
+ "B",
+ "D",
+ "E",
+ "F",
+ "I",
+ "ARG",
+ "BLE",
+ "C4",
+ "SIM",
+ "PLC",
+ "PLE",
+ "PLR",
+ "PLW",
+ "RUF",
+]
+ignore = ["B023", "D100", "D101", "D102", "D103", "D104", "D107", "D203"]
+
+# Exclude a variety of commonly ignored directories.
+exclude = [
+ ".bzr",
+ ".direnv",
+ ".eggs",
+ ".git",
+ ".hg",
+ ".mypy_cache",
+ ".nox",
+ ".pants.d",
+ ".ruff_cache",
+ ".svn",
+ ".tox",
+ ".venv",
+ "__pypackages__",
+ "_build",
+ "buck-out",
+ "build",
+ "dist",
+ "node_modules",
+ "venv",
+]
+
+# Allow unused variables when underscore-prefixed.
+dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+
+# Assume Python 3.10.
+target-version = "py310"
+
+[tool.ruff.pydocstyle]
+convention = "google"
+
+[tool.ruff.per-file-ignores]
+"src/anchorpy/coder/*.py" = ["ARG002"]
+"src/anchorpy/borsh_extension.py" = ["ARG002"]
+"tests/**/*.py" = ["ARG001", "E501"]
+"tests/client_gen/example_program_gen/**/*.py" = ["C417", "I001", "F401"]
+"tests/client_gen/token/**/*.py" = ["C417", "I001", "F401"]
+"src/anchorpy/cli.py" = ["B008"]
+
+[tool.pyright]
+reportMissingModuleSource = false
diff --git a/basics/anchorpy-main/pytest.ini b/basics/anchorpy-main/pytest.ini
new file mode 100644
index 0000000..b8aa1e9
--- /dev/null
+++ b/basics/anchorpy-main/pytest.ini
@@ -0,0 +1,5 @@
+[pytest]
+markers =
+ unit: mark a test as a unit test.
+addopts = -x
+asyncio_mode=strict
diff --git a/basics/anchorpy-main/src/anchorpy/__init__.py b/basics/anchorpy-main/src/anchorpy/__init__.py
new file mode 100644
index 0000000..9f4a059
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/__init__.py
@@ -0,0 +1,52 @@
+"""The Python Anchor client."""
+from anchorpy_core.idl import Idl
+
+from anchorpy import error, utils
+from anchorpy.coder.coder import AccountsCoder, Coder, EventCoder, InstructionCoder
+from anchorpy.idl import IdlProgramAccount
+from anchorpy.program.common import (
+ Event,
+ NamedInstruction,
+ translate_address,
+ validate_accounts,
+)
+from anchorpy.program.context import Context
+from anchorpy.program.core import Program
+from anchorpy.program.event import EventParser
+from anchorpy.program.namespace.account import AccountClient, ProgramAccount
+from anchorpy.program.namespace.simulate import SimulateResponse
+from anchorpy.provider import Provider, Wallet
+from anchorpy.pytest_plugin import bankrun_fixture, localnet_fixture, workspace_fixture
+from anchorpy.workspace import WorkspaceType, close_workspace, create_workspace
+
+__all__ = [
+ "Program",
+ "Provider",
+ "Context",
+ "bankrun_fixture",
+ "create_workspace",
+ "close_workspace",
+ "Idl",
+ "workspace_fixture",
+ "WorkspaceType",
+ "localnet_fixture",
+ "Wallet",
+ "Coder",
+ "InstructionCoder",
+ "EventCoder",
+ "AccountsCoder",
+ "NamedInstruction",
+ "IdlProgramAccount",
+ "Event",
+ "translate_address",
+ "validate_accounts",
+ "AccountClient",
+ "ProgramAccount",
+ "EventParser",
+ "SimulateResponse",
+ "error",
+ "utils",
+]
+
+
+__version__ = "0.18.0"
diff --git a/basics/anchorpy-main/src/anchorpy/borsh_extension.py b/basics/anchorpy-main/src/anchorpy/borsh_extension.py
new file mode 100644
index 0000000..bd7f058
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/borsh_extension.py
@@ -0,0 +1,121 @@
+"""Extensions to the Borsh spec for Solana-specific types."""
+from dataclasses import asdict
+from keyword import kwlist
+from typing import Any, Dict, Type, TypeVar, cast
+
+from borsh_construct import U8, CStruct
+from construct import (
+ Adapter,
+ Bytes,
+ Construct,
+ Container,
+ IfThenElse,
+ Padding,
+ Renamed,
+ Switch,
+)
+from solders import pubkey
+
+
+class BorshPubkeyAdapter(Adapter):
+ def __init__(self) -> None:
+ super().__init__(Bytes(32)) # type: ignore
+
+ def _decode(self, obj: bytes, context, path) -> pubkey.Pubkey:
+ return pubkey.Pubkey(obj)
+
+ def _encode(self, obj: pubkey.Pubkey, context, path) -> bytes:
+ return bytes(obj)
+
+
+class EnumForCodegen(Adapter):
+ _index_key = "index"
+ _value_key = "value"
+
+ def __init__(self, *variants: "Renamed[CStruct, CStruct]") -> None:
+ """Init enum."""
+ switch_cases: dict[int, "Renamed[CStruct, CStruct]"] = {}
+ variant_name_to_index: dict[str, int] = {}
+ index_to_variant_name: dict[int, str] = {}
+ for idx, parser in enumerate(variants):
+ switch_cases[idx] = parser
+ name = cast(str, parser.name)
+ variant_name_to_index[name] = idx
+ index_to_variant_name[idx] = name
+ enum_struct = CStruct(
+ self._index_key / U8,
+ self._value_key
+ / Switch(lambda this: this.index, cast(dict[int, Construct], switch_cases)),
+ )
+ super().__init__(enum_struct) # type: ignore
+ self.variant_name_to_index = variant_name_to_index
+ self.index_to_variant_name = index_to_variant_name
+
+ def _decode(self, obj: CStruct, context, path) -> dict[str, Any]:
+ index = obj.index
+ variant_name = self.index_to_variant_name[index]
+ return {variant_name: obj.value}
+
+ def _encode(self, obj: dict[str, Any], context, path) -> dict[str, Any]:
+ variant_name = list(obj.keys())[0]
+ index = self.variant_name_to_index[variant_name]
+ return {self._index_key: index, self._value_key: obj[variant_name]}
+
+
+class COption(Adapter):
+ _discriminator_key = "discriminator"
+ _value_key = "value"
+
+ def __init__(self, subcon: Construct) -> None:
+ option_struct = CStruct(
+ self._discriminator_key / U8,
+ self._value_key
+ / IfThenElse(
+ lambda this: this[self._discriminator_key] == 0,
+ Padding(subcon.sizeof()),
+ subcon,
+ ),
+ )
+ super().__init__(option_struct) # type: ignore
+
+ def _decode(self, obj, context, path) -> Any:
+ discriminator = obj[self._discriminator_key]
+ return None if discriminator == 0 else obj[self._value_key]
+
+ def _encode(self, obj, context, path) -> dict:
+ discriminator = 0 if obj is None else 1
+ return {self._discriminator_key: discriminator, self._value_key: obj}
+
+
+T = TypeVar("T")
+
+
+class _DataclassStruct(Adapter):
+ """Converts dataclasses to/from `borsh_construct.CStruct`."""
+
+ def __init__(self, cstruct: CStruct, datacls: Type[T]) -> None:
+ """Init.
+
+ Args:
+ cstruct: The underlying `CStruct`.
+ datacls: The dataclass type.
+ """
+ super().__init__(cstruct) # type: ignore
+ self.datacls = datacls
+
+ def _decode(self, obj: Container, context, path) -> T: # type: ignore
+ kwargs = {}
+ for key, value in obj.items():
+ if key[0] != "_":
+ key_to_use = f"{key}_" if key in kwlist else key
+ kwargs[key_to_use] = value
+ return self.datacls(**kwargs) # type: ignore
+
+ def _encode(self, obj: T, context, path) -> Dict[str, Any]:
+ if isinstance(obj, dict):
+ return obj
+ return asdict(obj)
+
+
+BorshPubkey = BorshPubkeyAdapter()
+"""Adapter for (de)serializing a public key."""
diff --git a/basics/anchorpy-main/src/anchorpy/cli.py b/basics/anchorpy-main/src/anchorpy/cli.py
new file mode 100644
index 0000000..d9f069a
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/cli.py
@@ -0,0 +1,142 @@
+import os
+from contextlib import contextmanager
+from pathlib import Path
+from typing import Optional, cast
+
+import typer
+from anchorpy_core.idl import Idl
+from IPython import embed
+
+from anchorpy import create_workspace
+from anchorpy.clientgen.accounts import gen_accounts
+from anchorpy.clientgen.errors import gen_errors
+from anchorpy.clientgen.instructions import gen_instructions
+from anchorpy.clientgen.program_id import gen_program_id
+from anchorpy.clientgen.types import gen_types
+from anchorpy.template import INIT_TESTS
+
+app = typer.Typer()
+
+
+@contextmanager
+def _set_directory(path: Path):
+ """Set the cwd within the context.
+
+ Args:
+ path (Path): The path to the cwd
+
+ Yields:
+ None
+ """ # noqa: D202
+
+ origin = Path().absolute()
+ try:
+ os.chdir(path)
+ yield
+ finally:
+ os.chdir(origin)
+
+
+def _search_upwards_for_project_root() -> Path:
+ """Search in the current dir and all directories above it for an Anchor.toml file.
+
+ Returns:
+ The location of the first Anchor.toml file found
+ """
+ search_dir = Path.cwd()
+ root = Path(search_dir.root)
+
+ while search_dir != root:
+ attempt = search_dir / "Anchor.toml"
+ if attempt.exists():
+ return search_dir
+ search_dir = search_dir.parent
+
+ raise FileNotFoundError("Not in Anchor workspace.")
+
+
+@app.callback()
+def callback():
+ """AnchorPy CLI."""
+
+
+@app.command()
+def shell():
+ """Start IPython shell with AnchorPy workspace object initialized.
+
+ Note that you should run `anchor localnet` before `anchorpy shell`.
+ """
+ path = _search_upwards_for_project_root()
+ workspace = create_workspace(path) # noqa: F841
+ embed(
+ colors="neutral",
+ using="asyncio",
+ banner2="Hint: type `workspace` to see the Anchor workspace object.\n",
+ )
+
+
+@app.command()
+def init(
+ program_name: str = typer.Argument(..., help="The name of the Anchor program.")
+):
+ """Create a basic Python test file for an Anchor program.
+
+ This does not replace `anchor init`, but rather should be
+ run after it.
+
+ The test file will live at `tests/test_$PROGRAM_NAME.py`.
+ """
+ file_contents = INIT_TESTS.format(program_name)
+ project_root = _search_upwards_for_project_root()
+ file_path = project_root / "tests" / f"test_{program_name}.py"
+ if file_path.exists():
+ raise FileExistsError(file_path)
+ file_path.write_text(file_contents)
+
+
+@app.command()
+def client_gen(
+ idl: Path = typer.Argument(..., help="Anchor IDL file path"),
+ out: Path = typer.Argument(..., help="Output directory."),
+ program_id: Optional[str] = typer.Option(
+ None, help="Optional program ID to be included in the code"
+ ),
+ pdas: bool = typer.Option(
+ False, "--pdas", help="Auto-generate PDAs where possible."
+ ),
+):
+ """Generate Python client code from the specified anchor IDL."""
+ idl_obj = Idl.from_json(idl.read_text())
+ if program_id is None:
+ idl_metadata = idl_obj.metadata
+ address_from_idl = (
+ idl_metadata["address"] if isinstance(idl_metadata, dict) else None
+ )
+ if address_from_idl is None:
+ typer.echo(
+ "No program ID found in IDL. Use the --program-id "
+ "option to set it manually."
+ )
+ raise typer.Exit(code=1)
+ else:
+ program_id_to_use = cast(str, address_from_idl)
+ else:
+ program_id_to_use = program_id
+
+ typer.echo("generating package...")
+ out.mkdir(exist_ok=True)
+ (out / "__init__.py").touch()
+ typer.echo("generating program_id.py...")
+ gen_program_id(program_id_to_use, out)
+ typer.echo("generating errors.py...")
+ gen_errors(idl_obj, out)
+ typer.echo("generating instructions...")
+ gen_instructions(idl_obj, out, pdas)
+ typer.echo("generating types...")
+ gen_types(idl_obj, out)
+ typer.echo("generating accounts...")
+ gen_accounts(idl_obj, out)
+
+
+if __name__ == "__main__":
+ app()
diff --git a/basics/anchorpy-main/src/anchorpy/clientgen/__init__.py b/basics/anchorpy-main/src/anchorpy/clientgen/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/basics/anchorpy-main/src/anchorpy/clientgen/accounts.py b/basics/anchorpy-main/src/anchorpy/clientgen/accounts.py
new file mode 100644
index 0000000..3629989
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/clientgen/accounts.py
@@ -0,0 +1,303 @@
+from pathlib import Path
+from typing import cast
+
+from anchorpy_core.idl import (
+ Idl,
+ IdlField,
+ IdlTypeDefinition,
+ IdlTypeDefinitionTyStruct,
+)
+from autoflake import fix_code
+from black import FileMode, format_str
+from genpy import (
+ Assign,
+ Collection,
+ For,
+ FromImport,
+ If,
+ Import,
+ ImportAs,
+ Raise,
+ Return,
+ Statement,
+ Suite,
+)
+from pyheck import snake
+
+from anchorpy.clientgen.common import (
+ _field_from_decoded,
+ _field_from_json,
+ _field_to_json,
+ _idl_type_to_json_type,
+ _json_interface_name,
+ _layout_for_type,
+ _py_type_from_idl,
+ _sanitize,
+)
+from anchorpy.clientgen.genpy_extension import (
+ Call,
+ ClassMethod,
+ Continue,
+ Dataclass,
+ Method,
+ NamedArg,
+ StrDict,
+ StrDictEntry,
+ TypedDict,
+ TypedParam,
+)
+from anchorpy.coder.accounts import _account_discriminator
+
+
+def gen_accounts(idl: Idl, root: Path) -> None:
+ accounts = idl.accounts
+ if accounts is None or not accounts:
+ return
+ accounts_dir = root / "accounts"
+ accounts_dir.mkdir(exist_ok=True)
+ gen_index_file(idl, accounts_dir)
+ accounts_dict = gen_accounts_code(idl, accounts_dir)
+ for path, code in accounts_dict.items():
+ formatted = format_str(code, mode=FileMode())
+ fixed = fix_code(formatted, remove_all_unused_imports=True)
+ path.write_text(fixed)
+
+
+def gen_index_file(idl: Idl, accounts_dir: Path) -> None:
+ code = gen_index_code(idl)
+ formatted = format_str(code, mode=FileMode())
+ (accounts_dir / "__init__.py").write_text(formatted)
+
+
+def gen_index_code(idl: Idl) -> str:
+ imports: list[FromImport] = []
+ for acc in idl.accounts:
+ acc_name = _sanitize(acc.name)
+ members = [
+ acc_name,
+ _json_interface_name(acc_name),
+ ]
+ module_name = _sanitize(snake(acc.name))
+ imports.append(FromImport(f".{module_name}", members))
+ return str(Collection(imports))
+
+
+def gen_accounts_code(idl: Idl, accounts_dir: Path) -> dict[Path, str]:
+ res = {}
+ for acc in idl.accounts:
+ filename = f"{_sanitize(snake(acc.name))}.py"
+ path = accounts_dir / filename
+ code = gen_account_code(acc, idl)
+ res[path] = code
+ return res
+
+
+def gen_account_code(acc: IdlTypeDefinition, idl: Idl) -> str:
+ base_imports = [
+ Import("typing"),
+ FromImport("dataclasses", ["dataclass"]),
+ FromImport("construct", ["Construct"]),
+ FromImport("solders.pubkey", ["Pubkey"]),
+ FromImport("solana.rpc.async_api", ["AsyncClient"]),
+ FromImport("solana.rpc.commitment", ["Commitment"]),
+ ImportAs("borsh_construct", "borsh"),
+ FromImport("anchorpy.coder.accounts", ["ACCOUNT_DISCRIMINATOR_SIZE"]),
+ FromImport("anchorpy.error", ["AccountInvalidDiscriminator"]),
+ FromImport("anchorpy.utils.rpc", ["get_multiple_accounts"]),
+ FromImport(
+ "anchorpy.borsh_extension", ["BorshPubkey", "EnumForCodegen", "COption"]
+ ),
+ FromImport("..program_id", ["PROGRAM_ID"]),
+ ]
+ imports = (
+ [*base_imports, FromImport("..", ["types"])] if idl.types else base_imports
+ )
+ fields_interface_params: list[TypedParam] = []
+ json_interface_params: list[TypedParam] = []
+ ty = cast(IdlTypeDefinitionTyStruct, acc.ty)
+ fields = ty.fields
+ name = _sanitize(acc.name)
+ json_interface_name = _json_interface_name(name)
+ layout_items: list[str] = []
+ init_body_assignments: list[Assign] = []
+ decode_body_entries: list[NamedArg] = []
+ to_json_entries: list[StrDictEntry] = []
+ from_json_entries: list[NamedArg] = []
+ for field in fields:
+ field_name = _sanitize(snake(field.name))
+ fields_interface_params.append(
+ TypedParam(
+ field_name,
+ _py_type_from_idl(
+ idl=idl,
+ ty=field.ty,
+ types_relative_imports=False,
+ use_fields_interface_for_struct=False,
+ ),
+ )
+ )
+ json_interface_params.append(
+ TypedParam(
+ field_name,
+ _idl_type_to_json_type(ty=field.ty, types_relative_imports=False),
+ )
+ )
+ layout_items.append(
+ _layout_for_type(
+ idl=idl, ty=field.ty, name=field_name, types_relative_imports=False
+ )
+ )
+ init_body_assignments.append(
+ Assign(f"self.{field_name}", f'fields["{field_name}"]')
+ )
+ decode_body_entries.append(
+ NamedArg(
+ field_name,
+ _field_from_decoded(
+ idl=idl,
+ ty=IdlField(name=snake(field.name), docs=None, ty=field.ty),
+ types_relative_imports=False,
+ val_prefix="dec.",
+ ),
+ )
+ )
+ to_json_entries.append(
+ StrDictEntry(field_name, _field_to_json(idl, field, "self."))
+ )
+ from_json_entries.append(
+ NamedArg(
+ field_name,
+ _field_from_json(idl=idl, ty=field, types_relative_imports=False),
+ )
+ )
+ json_interface = TypedDict(json_interface_name, json_interface_params)
+ discriminator_assignment = Assign(
+ "discriminator: typing.ClassVar", _account_discriminator(name)
+ )
+ layout_assignment = Assign(
+ "layout: typing.ClassVar", f"borsh.CStruct({','.join(layout_items)})"
+ )
+ fetch_method = ClassMethod(
+ "fetch",
+ [
+ TypedParam("conn", "AsyncClient"),
+ TypedParam("address", "Pubkey"),
+ TypedParam("commitment", "typing.Optional[Commitment] = None"),
+ TypedParam("program_id", "Pubkey = PROGRAM_ID"),
+ ],
+ Suite(
+ [
+ Assign(
+ "resp",
+ "await conn.get_account_info(address, commitment=commitment)",
+ ),
+ Assign("info", "resp.value"),
+ If("info is None", Return("None")),
+ If(
+ "info.owner != program_id",
+ Raise('ValueError("Account does not belong to this program")'),
+ ),
+ Assign("bytes_data", "info.data"),
+ Return("cls.decode(bytes_data)"),
+ ]
+ ),
+ f'typing.Optional["{name}"]',
+ is_async=True,
+ )
+ account_does_not_belong_raise = Raise(
+ 'ValueError("Account does not belong to this program")'
+ )
+ fetch_multiple_return_type = f'typing.List[typing.Optional["{name}"]]'
+ fetch_multiple_method = ClassMethod(
+ "fetch_multiple",
+ [
+ TypedParam("conn", "AsyncClient"),
+ TypedParam("addresses", "list[Pubkey]"),
+ TypedParam("commitment", "typing.Optional[Commitment] = None"),
+ TypedParam("program_id", "Pubkey = PROGRAM_ID"),
+ ],
+ Suite(
+ [
+ Assign(
+ "infos",
+ (
+ "await get_multiple_accounts"
+ "(conn, addresses,commitment=commitment)"
+ ),
+ ),
+ Assign(f"res: {fetch_multiple_return_type}", "[]"),
+ For(
+ "info",
+ "infos",
+ Suite(
+ [
+ If(
+ "info is None",
+ Suite([Statement("res.append(None)"), Continue()]),
+ ),
+ If(
+ "info.account.owner != program_id",
+ account_does_not_belong_raise,
+ ),
+ Statement("res.append(cls.decode(info.account.data))"),
+ ]
+ ),
+ ),
+ Return("res"),
+ ]
+ ),
+ f'typing.List[typing.Optional["{name}"]]',
+ is_async=True,
+ )
+ decode_body_end = Call("cls", decode_body_entries)
+ account_invalid_raise = Raise(
+ 'AccountInvalidDiscriminator("The discriminator for this account is invalid")'
+ )
+ decode_method = ClassMethod(
+ "decode",
+ [TypedParam("data", "bytes")],
+ Suite(
+ [
+ If(
+ "data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator",
+ account_invalid_raise,
+ ),
+ Assign(
+ "dec", f"{name}.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])"
+ ),
+ Return(decode_body_end),
+ ]
+ ),
+ f'"{name}"',
+ )
+ to_json_body = StrDict(to_json_entries)
+ to_json_method = Method("to_json", [], Return(to_json_body), json_interface_name)
+ from_json_body = Call("cls", from_json_entries)
+ from_json_method = ClassMethod(
+ "from_json",
+ [TypedParam("obj", json_interface_name)],
+ Return(from_json_body),
+ f'"{name}"',
+ )
+ klass = Dataclass(
+ name,
+ [
+ discriminator_assignment,
+ layout_assignment,
+ *fields_interface_params,
+ fetch_method,
+ fetch_multiple_method,
+ decode_method,
+ to_json_method,
+ from_json_method,
+ ],
+ )
+ return str(
+ Collection(
+ [
+ *imports,
+ json_interface,
+ klass,
+ ]
+ )
+ )
diff --git a/basics/anchorpy-main/src/anchorpy/clientgen/common.py b/basics/anchorpy-main/src/anchorpy/clientgen/common.py
new file mode 100644
index 0000000..f12b268
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/clientgen/common.py
@@ -0,0 +1,636 @@
+"""Code generation utilities."""
+import keyword
+from typing import Optional
+
+from anchorpy_core.idl import (
+ Idl,
+ IdlField,
+ IdlType,
+ IdlTypeArray,
+ IdlTypeDefined,
+ IdlTypeDefinitionTyStruct,
+ IdlTypeOption,
+ IdlTypeSimple,
+ IdlTypeVec,
+)
+from pyheck import snake
+
+_DEFAULT_DEFINED_TYPES_PREFIX = "types."
+
+INT_TYPES = {
+ IdlTypeSimple.U8,
+ IdlTypeSimple.I8,
+ IdlTypeSimple.U16,
+ IdlTypeSimple.I16,
+ IdlTypeSimple.U32,
+ IdlTypeSimple.I32,
+ IdlTypeSimple.U64,
+ IdlTypeSimple.I64,
+ IdlTypeSimple.U128,
+ IdlTypeSimple.I128,
+}
+FLOAT_TYPES = {IdlTypeSimple.F32, IdlTypeSimple.F64}
+NUMBER_TYPES = INT_TYPES | FLOAT_TYPES
+
+
+def _fields_interface_name(type_name: str) -> str:
+ return f"{type_name}Fields"
+
+
+def _value_interface_name(type_name: str) -> str:
+ return f"{type_name}Value"
+
+
+def _kind_interface_name(type_name: str) -> str:
+ return f"{type_name}Kind"
+
+
+def _json_interface_name(type_name: str) -> str:
+ return f"{type_name}JSON"
+
+
+def _sanitize(name: str) -> str:
+ return f"{name}_" if keyword.iskeyword(name) else name
+
+
+def _py_type_from_idl(
+ idl: Idl,
+ ty: IdlType,
+ types_relative_imports: bool,
+ use_fields_interface_for_struct: bool,
+) -> str:
+ if isinstance(ty, IdlTypeVec):
+ inner_type = _py_type_from_idl(
+ idl=idl,
+ ty=ty.vec,
+ types_relative_imports=types_relative_imports,
+ use_fields_interface_for_struct=use_fields_interface_for_struct,
+ )
+ return f"list[{inner_type}]"
+ if isinstance(ty, IdlTypeOption):
+ inner_type = _py_type_from_idl(
+ idl=idl,
+ ty=ty.option,
+ types_relative_imports=types_relative_imports,
+ use_fields_interface_for_struct=use_fields_interface_for_struct,
+ )
+ return f"typing.Optional[{inner_type}]"
+ if isinstance(ty, IdlTypeDefined):
+ defined = _sanitize(ty.defined)
+ filtered = [t for t in idl.types if _sanitize(t.name) == defined]
+ maybe_coption_split = defined.split("COption<")
+ if len(maybe_coption_split) == 2:
+ inner_type = {"u64": "int", "Pubkey": "Pubkey"}[maybe_coption_split[1][:-1]]
+ return f"typing.Optional[{inner_type}]"
+ if defined == "&'astr":
+ return "str"
+ defined_types_prefix = (
+ "" if types_relative_imports else _DEFAULT_DEFINED_TYPES_PREFIX
+ )
+ if len(filtered) != 1:
+ raise ValueError(f"Type not found {defined}")
+ typedef_type = filtered[0].ty
+ module = _sanitize(snake(ty.defined))
+ if isinstance(typedef_type, IdlTypeDefinitionTyStruct):
+ name = (
+ _fields_interface_name(ty.defined)
+ if use_fields_interface_for_struct
+ else defined
+ )
+ else:
+ # enum
+ name = _kind_interface_name(ty.defined)
+ return f"{defined_types_prefix}{module}.{name}"
+ if isinstance(ty, IdlTypeArray):
+ inner_type = _py_type_from_idl(
+ idl=idl,
+ ty=ty.array[0],
+ types_relative_imports=types_relative_imports,
+ use_fields_interface_for_struct=use_fields_interface_for_struct,
+ )
+ return f"list[{inner_type}]"
+ if ty in {IdlTypeSimple.Bool, IdlTypeSimple.Bytes}:
+ return str(ty).replace("IdlTypeSimple.", "").lower()
+ if ty in INT_TYPES:
+ return "int"
+ if ty in FLOAT_TYPES:
+ return "float"
+ if ty == IdlTypeSimple.String:
+ return "str"
+ if ty == IdlTypeSimple.PublicKey:
+ return "Pubkey"
+ raise ValueError(f"Unrecognized type: {ty}")
+
+
+def _layout_for_type(
+ idl: Idl,
+ ty: IdlType,
+ types_relative_imports: bool,
+ name: Optional[str] = None,
+) -> str:
+ if ty == IdlTypeSimple.PublicKey:
+ inner = "BorshPubkey"
+ elif isinstance(ty, IdlTypeSimple):
+ inner = str(ty).replace("IdlTypeSimple", "borsh")
+ elif isinstance(ty, IdlTypeVec):
+ layout = _layout_for_type(
+ idl=idl, ty=ty.vec, types_relative_imports=types_relative_imports
+ )
+ cast_layout = f"typing.cast(Construct, {layout})"
+ inner = f"borsh.Vec({cast_layout})"
+ elif isinstance(ty, IdlTypeOption):
+ layout = _layout_for_type(
+ idl=idl, ty=ty.option, types_relative_imports=types_relative_imports
+ )
+ inner = f"borsh.Option({layout})"
+ elif isinstance(ty, IdlTypeDefined):
+ defined = _sanitize(ty.defined)
+ maybe_coption_split = defined.split("COption<")
+ if len(maybe_coption_split) == 2:
+ layout_str = maybe_coption_split[1][:-1]
+ layout = {"u64": "borsh.U64", "Pubkey": "BorshPubkey"}[layout_str]
+ inner = f"COption({layout})"
+ elif defined == "&'astr":
+ return "borsh.String"
+ else:
+ filtered = [t for t in idl.types if _sanitize(t.name) == defined]
+ typedef_type = filtered[0].ty
+ defined_types_prefix = (
+ "" if types_relative_imports else _DEFAULT_DEFINED_TYPES_PREFIX
+ )
+ module = snake(defined)
+ inner = (
+ f"{defined_types_prefix}{module}.{defined}.layout"
+ if isinstance(typedef_type, IdlTypeDefinitionTyStruct)
+ else f"{defined_types_prefix}{module}.layout"
+ )
+ elif isinstance(ty, IdlTypeArray):
+ layout = _layout_for_type(
+ idl=idl, ty=ty.array[0], types_relative_imports=types_relative_imports
+ )
+ inner = f"{layout}[{ty.array[1]}]"
+ else:
+ raise ValueError(f"Unrecognized type: {ty}")
+
+ if name is None:
+ return inner
+ return f'"{name}" / {inner}'
+
+
+def _maybe_none(to_check: str, if_not_none: str) -> str:
+ return f"(None if {to_check} is None else {if_not_none})"
+
+
+def _field_to_encodable(
+ idl: Idl,
+ ty: IdlField,
+ types_relative_imports: bool,
+ val_prefix: str = "",
+ val_suffix: str = "",
+ convert_case: bool = True,
+) -> str:
+ ty_type = ty.ty
+ maybe_converted = snake(ty.name) if convert_case else ty.name
+ ty_name = _sanitize(maybe_converted)
+ if isinstance(ty_type, IdlTypeVec):
+ map_body = _field_to_encodable(
+ idl=idl,
+ ty=IdlField("item", docs=None, ty=ty_type.vec),
+ val_prefix="",
+ types_relative_imports=types_relative_imports,
+ val_suffix="",
+ )
+ # skip mapping when not needed
+ if map_body == "item":
+ return f"{val_prefix}{ty_name}{val_suffix}"
+ return f"list(map(lambda item: {map_body}, {val_prefix}{ty_name}{val_suffix}))"
+ if isinstance(ty_type, IdlTypeOption):
+ encodable = _field_to_encodable(
+ idl=idl,
+ ty=IdlField(ty_name, docs=None, ty=ty_type.option),
+ val_prefix=val_prefix,
+ types_relative_imports=types_relative_imports,
+ val_suffix=val_suffix,
+ convert_case=convert_case,
+ )
+ if encodable == f"{val_prefix}{ty_name}{val_suffix}":
+ return encodable
+ return _maybe_none(f"{val_prefix}{ty_name}{val_suffix}", encodable)
+ if isinstance(ty_type, IdlTypeDefined):
+ defined = _sanitize(ty_type.defined)
+ maybe_coption_split = defined.split("COption<")
+ if len(maybe_coption_split) == 2:
+ inner_type = maybe_coption_split[1][:-1]
+ encodable = _field_to_encodable(
+ idl=idl,
+ ty=IdlField(
+ ty_name,
+ docs=None,
+ ty={"u64": IdlTypeSimple.U64, "Pubkey": IdlTypeSimple.PublicKey}[
+ inner_type
+ ],
+ ),
+ val_prefix=val_prefix,
+ types_relative_imports=types_relative_imports,
+ val_suffix=val_suffix,
+ convert_case=convert_case,
+ )
+ if encodable == f"{val_prefix}{ty_name}{val_suffix}":
+ return encodable
+ return _maybe_none(f"{val_prefix}{ty_name}{val_suffix}", encodable)
+ elif defined == "&'astr":
+ return f"{val_prefix}{ty_name}{val_suffix}"
+ filtered = [t for t in idl.types if _sanitize(t.name) == defined]
+
+ if len(filtered) != 1:
+ raise ValueError(f"Type not found {defined}")
+ typedef_type = filtered[0].ty
+ if isinstance(typedef_type, IdlTypeDefinitionTyStruct):
+ val_full_name = f"{val_prefix}{ty_name}{val_suffix}"
+ return f"{val_full_name}.to_encodable()"
+ return f"{val_prefix}{ty_name}{val_suffix}.to_encodable()"
+ if isinstance(ty_type, IdlTypeArray):
+ map_body = _field_to_encodable(
+ idl=idl,
+ ty=IdlField("item", docs=None, ty=ty_type.array[0]),
+ val_prefix="",
+ types_relative_imports=types_relative_imports,
+ val_suffix="",
+ )
+ # skip mapping when not needed
+ if map_body == "item":
+ return f"{val_prefix}{ty_name}{val_suffix}"
+ return f"list(map(lambda item: {map_body}, {val_prefix}{ty_name}{val_suffix}))"
+ if ty_type in {
+ IdlTypeSimple.Bool,
+ *NUMBER_TYPES,
+ IdlTypeSimple.String,
+ IdlTypeSimple.PublicKey,
+ IdlTypeSimple.Bytes,
+ }:
+ return f"{val_prefix}{ty_name}{val_suffix}"
+ raise ValueError(f"Unrecognized type: {ty_type}")
+
+
+def _field_from_decoded(
+ idl: Idl, ty: IdlField, types_relative_imports: bool, val_prefix: str = ""
+) -> str:
+ ty_type = ty.ty
+ ty_name = _sanitize(ty.name)
+ if isinstance(ty_type, IdlTypeVec):
+ map_body = _field_from_decoded(
+ idl=idl,
+ ty=IdlField("item", docs=None, ty=ty_type.vec),
+ val_prefix="",
+ types_relative_imports=types_relative_imports,
+ )
+ # skip mapping when not needed
+ if map_body == "item":
+ return f"{val_prefix}{ty_name}"
+ return f"list(map(lambda item: {map_body}, {val_prefix}{ty_name}))"
+ if isinstance(ty_type, IdlTypeOption):
+ decoded = _field_from_decoded(
+ idl=idl,
+ ty=IdlField(ty_name, docs=None, ty=ty_type.option),
+ types_relative_imports=types_relative_imports,
+ val_prefix=val_prefix,
+ )
+ # skip coercion when not needed
+ if decoded == f"{val_prefix}{ty_name}":
+ return decoded
+ return _maybe_none(f"{val_prefix}{ty_name}", decoded)
+ if isinstance(ty_type, IdlTypeDefined):
+ defined = _sanitize(ty_type.defined)
+ maybe_coption_split = defined.split("COption<")
+ if len(maybe_coption_split) == 2:
+ inner_type = maybe_coption_split[1][:-1]
+ decoded = _field_from_decoded(
+ idl=idl,
+ ty=IdlField(
+ ty_name,
+ docs=None,
+ ty={"u64": IdlTypeSimple.U64, "Pubkey": IdlTypeSimple.PublicKey}[
+ inner_type
+ ],
+ ),
+ types_relative_imports=types_relative_imports,
+ val_prefix=val_prefix,
+ )
+ # skip coercion when not needed
+ if decoded == f"{val_prefix}{ty_name}":
+ return decoded
+ return _maybe_none(f"{val_prefix}{ty_name}", decoded)
+ filtered = [t for t in idl.types if _sanitize(t.name) == defined]
+ if len(filtered) != 1:
+ raise ValueError(f"Type not found {defined}")
+ typedef_type = filtered[0].ty
+ from_decoded_func_path = (
+ f"{snake(defined)}.{defined}"
+ if isinstance(typedef_type, IdlTypeDefinitionTyStruct)
+ else f"{snake(defined)}"
+ )
+ defined_types_prefix = (
+ "" if types_relative_imports else _DEFAULT_DEFINED_TYPES_PREFIX
+ )
+ full_func_path = f"{defined_types_prefix}{from_decoded_func_path}"
+ from_decoded_arg = f"{val_prefix}{ty_name}"
+ return f"{full_func_path}.from_decoded({from_decoded_arg})"
+ if isinstance(ty_type, IdlTypeArray):
+ map_body = _field_from_decoded(
+ idl=idl,
+ ty=IdlField("item", docs=None, ty=ty_type.array[0]),
+ val_prefix="",
+ types_relative_imports=types_relative_imports,
+ )
+ # skip mapping when not needed
+ if map_body == "item":
+ return f"{val_prefix}{ty_name}"
+ return f"list(map(lambda item: {map_body}, {val_prefix}{ty_name}))"
+ if ty_type in {
+ IdlTypeSimple.Bool,
+ *NUMBER_TYPES,
+ IdlTypeSimple.String,
+ IdlTypeSimple.PublicKey,
+ IdlTypeSimple.Bytes,
+ }:
+ return f"{val_prefix}{ty_name}"
+ raise ValueError(f"Unrecognized type: {ty_type}")
+
+
+def _struct_field_initializer(
+ idl: Idl,
+ field: IdlField,
+ types_relative_imports: bool,
+ prefix: str = 'fields["',
+ suffix: str = '"]',
+) -> str:
+ field_type = field.ty
+ field_name = _sanitize(snake(field.name))
+ if isinstance(field_type, IdlTypeDefined):
+ defined = _sanitize(field_type.defined)
+ filtered = [t for t in idl.types if _sanitize(t.name) == defined]
+ if len(filtered) != 1:
+ raise ValueError(f"Type not found {defined}")
+ typedef_type = filtered[0].ty
+ if isinstance(typedef_type, IdlTypeDefinitionTyStruct):
+ module = snake(defined)
+ defined_types_prefix = (
+ "" if types_relative_imports else _DEFAULT_DEFINED_TYPES_PREFIX
+ )
+ obj_name = f"{defined_types_prefix}{module}.{defined}"
+ return f"{obj_name}(**{prefix}{field_name}{suffix})"
+ return f"{prefix}{field_name}{suffix}"
+ if isinstance(field_type, IdlTypeOption):
+ initializer = _struct_field_initializer(
+ idl=idl,
+ field=IdlField(field_name, docs=None, ty=field_type.option),
+ prefix=prefix,
+ suffix=suffix,
+ types_relative_imports=types_relative_imports,
+ )
+ # skip coercion when not needed
+ if initializer == f"{prefix}{field_name}{suffix}":
+ return initializer
+ return _maybe_none(f"{prefix}{field_name}{suffix}", initializer)
+ if isinstance(field_type, IdlTypeArray):
+ map_body = _struct_field_initializer(
+ idl=idl,
+ field=IdlField("item", docs=None, ty=field_type.array[0]),
+ prefix="",
+ suffix="",
+ types_relative_imports=types_relative_imports,
+ )
+ # skip mapping when not needed
+ if map_body == "item":
+ return f"{prefix}{field_name}{suffix}"
+ return f"list(map(lambda item: {map_body}, {prefix}{field_name}{suffix}))"
+ if isinstance(field_type, IdlTypeVec):
+ map_body = _struct_field_initializer(
+ idl=idl,
+ field=IdlField("item", docs=None, ty=field_type.vec),
+ prefix="",
+ suffix="",
+ types_relative_imports=types_relative_imports,
+ )
+ # skip mapping when not needed
+ if map_body == "item":
+ return f"{prefix}{field_name}{suffix}"
+ return f"list(map(lambda item: {map_body}, {prefix}{field_name}{suffix}))"
+ if field_type in {
+ IdlTypeSimple.Bool,
+ *NUMBER_TYPES,
+ IdlTypeSimple.String,
+ IdlTypeSimple.PublicKey,
+ IdlTypeSimple.Bytes,
+ }:
+ return f"{prefix}{field_name}{suffix}"
+ raise ValueError(f"Unrecognized type: {field_type}")
+
+
+def _field_to_json(
+ idl: Idl,
+ ty: IdlField,
+ val_prefix: str = "",
+ val_suffix: str = "",
+ convert_case: bool = True,
+) -> str:
+ ty_type = ty.ty
+ maybe_converted = _sanitize(snake(ty.name)) if convert_case else _sanitize(ty.name)
+ var_name = f"{val_prefix}{maybe_converted}{val_suffix}"
+ if ty_type == IdlTypeSimple.PublicKey:
+ return f"str({var_name})"
+ if isinstance(ty_type, IdlTypeVec):
+ map_body = _field_to_json(idl, IdlField("item", docs=None, ty=ty_type.vec))
+ # skip mapping when not needed
+ if map_body == "item":
+ return var_name
+ return f"list(map(lambda item: {map_body}, {var_name}))"
+ if isinstance(ty_type, IdlTypeArray):
+ map_body = _field_to_json(idl, IdlField("item", docs=None, ty=ty_type.array[0]))
+ # skip mapping when not needed
+ if map_body == "item":
+ return var_name
+ return f"list(map(lambda item: {map_body}, {var_name}))"
+ if isinstance(ty_type, IdlTypeOption):
+ value = _field_to_json(
+ idl,
+ IdlField(ty.name, docs=None, ty=ty_type.option),
+ val_prefix,
+ val_suffix,
+ convert_case=convert_case,
+ )
+ # skip coercion when not needed
+ if value == var_name:
+ return value
+ return _maybe_none(var_name, value)
+ if isinstance(ty_type, IdlTypeDefined):
+ defined = ty_type.defined
+ filtered = [t for t in idl.types if t.name == defined]
+ maybe_coption_split = defined.split("COption<")
+ if len(maybe_coption_split) == 2:
+ inner_type = maybe_coption_split[1][:-1]
+ value = _field_to_json(
+ idl,
+ IdlField(
+ ty.name,
+ docs=None,
+ ty={"u64": IdlTypeSimple.U64, "Pubkey": IdlTypeSimple.PublicKey}[
+ inner_type
+ ],
+ ),
+ val_prefix,
+ val_suffix,
+ convert_case=convert_case,
+ )
+ # skip coercion when not needed
+ if value == var_name:
+ return value
+ return _maybe_none(var_name, value)
+ if len(filtered) != 1:
+ raise ValueError(f"Type not found {defined}")
+ return f"{var_name}.to_json()"
+ if ty_type == IdlTypeSimple.Bytes:
+ return f"list({var_name})"
+ if ty_type in {
+ IdlTypeSimple.Bool,
+ *NUMBER_TYPES,
+ IdlTypeSimple.String,
+ }:
+ return var_name
+ raise ValueError(f"Unrecognized type: {ty_type}")
+
+
+def _idl_type_to_json_type(ty: IdlType, types_relative_imports: bool) -> str:
+ if isinstance(ty, IdlTypeVec):
+ inner = _idl_type_to_json_type(
+ ty=ty.vec, types_relative_imports=types_relative_imports
+ )
+ return f"list[{inner}]"
+ if isinstance(ty, IdlTypeArray):
+ inner = _idl_type_to_json_type(
+ ty=ty.array[0], types_relative_imports=types_relative_imports
+ )
+ return f"list[{inner}]"
+ if isinstance(ty, IdlTypeOption):
+ inner = _idl_type_to_json_type(
+ ty=ty.option, types_relative_imports=types_relative_imports
+ )
+ return f"typing.Optional[{inner}]"
+ if isinstance(ty, IdlTypeDefined):
+ defined = ty.defined
+ maybe_coption_split = defined.split("COption<")
+ if len(maybe_coption_split) == 2:
+ inner_type = {"u64": "int", "Pubkey": "str"}[maybe_coption_split[1][:-1]]
+ return f"typing.Optional[{inner_type}]"
+ defined_types_prefix = (
+ "" if types_relative_imports else _DEFAULT_DEFINED_TYPES_PREFIX
+ )
+ module = _sanitize(snake(defined))
+ return f"{defined_types_prefix}{module}.{_json_interface_name(defined)}"
+ if ty == IdlTypeSimple.Bool:
+ return "bool"
+ if ty in INT_TYPES:
+ return "int"
+ if ty in FLOAT_TYPES:
+ return "float"
+ if ty == IdlTypeSimple.Bytes:
+ return "list[int]"
+ if ty in {IdlTypeSimple.String, IdlTypeSimple.PublicKey}:
+ return "str"
+ raise ValueError(f"Unrecognized type: {ty}")
+
+
+def _field_from_json(
+ idl: Idl,
+ ty: IdlField,
+ types_relative_imports: bool,
+ param_prefix: str = 'obj["',
+ param_suffix: str = '"]',
+) -> str:
+ ty_type = ty.ty
+ ty_name_snake_unsanitized = snake(ty.name)
+ ty_name = _sanitize(ty_name_snake_unsanitized)
+ var_name = f"{param_prefix}{ty_name_snake_unsanitized}{param_suffix}"
+ if ty_type == IdlTypeSimple.PublicKey:
+ return f"Pubkey.from_string({var_name})"
+ if isinstance(ty_type, IdlTypeVec):
+ map_body = _field_from_json(
+ idl=idl,
+ ty=IdlField("item", docs=None, ty=ty_type.vec),
+ param_prefix="",
+ param_suffix="",
+ types_relative_imports=types_relative_imports,
+ )
+ # skip mapping when not needed
+ if map_body == "item":
+ return var_name
+ return f"list(map(lambda item: {map_body}, {var_name}))"
+ if isinstance(ty_type, IdlTypeArray):
+ map_body = _field_from_json(
+ idl=idl,
+ ty=IdlField("item", docs=None, ty=ty_type.array[0]),
+ param_prefix="",
+ param_suffix="",
+ types_relative_imports=types_relative_imports,
+ )
+ # skip mapping when not needed
+ if map_body == "item":
+ return var_name
+ return f"list(map(lambda item: {map_body}, {var_name}))"
+ if isinstance(ty_type, IdlTypeOption):
+ inner = _field_from_json(
+ idl=idl,
+ ty=IdlField(ty_name, docs=None, ty=ty_type.option),
+ param_prefix=param_prefix,
+ param_suffix=param_suffix,
+ types_relative_imports=types_relative_imports,
+ )
+ # skip coercion when not needed
+ if inner == var_name:
+ return inner
+ return _maybe_none(var_name, inner)
+ if isinstance(ty_type, IdlTypeDefined):
+ from_json_arg = var_name
+ defined = _sanitize(ty_type.defined)
+ maybe_coption_split = defined.split("COption<")
+ if len(maybe_coption_split) == 2:
+ inner_type = maybe_coption_split[1][:-1]
+ inner = _field_from_json(
+ idl=idl,
+ ty=IdlField(
+ ty_name,
+ docs=None,
+ ty={"u64": IdlTypeSimple.U64, "Pubkey": IdlTypeSimple.PublicKey}[
+ inner_type
+ ],
+ ),
+ param_prefix=param_prefix,
+ param_suffix=param_suffix,
+ types_relative_imports=types_relative_imports,
+ )
+ # skip coercion when not needed
+ if inner == var_name:
+ return inner
+ return _maybe_none(var_name, inner)
+ defined_snake = _sanitize(snake(ty_type.defined))
+ filtered = [t for t in idl.types if _sanitize(t.name) == defined]
+ typedef_type = filtered[0].ty
+ from_json_func_path = (
+ f"{defined_snake}.{defined}"
+ if isinstance(typedef_type, IdlTypeDefinitionTyStruct)
+ else f"{defined_snake}"
+ )
+ defined_types_prefix = (
+ "" if types_relative_imports else _DEFAULT_DEFINED_TYPES_PREFIX
+ )
+ full_func_path = f"{defined_types_prefix}{from_json_func_path}"
+ return f"{full_func_path}.from_json({from_json_arg})"
+ if ty_type == IdlTypeSimple.Bytes:
+ return f"bytes({var_name})"
+ if ty_type in {
+ IdlTypeSimple.Bool,
+ *NUMBER_TYPES,
+ IdlTypeSimple.String,
+ }:
+ return var_name
+ raise ValueError(f"Unrecognized type: {ty_type}")
diff --git a/basics/anchorpy-main/src/anchorpy/clientgen/errors.py b/basics/anchorpy-main/src/anchorpy/clientgen/errors.py
new file mode 100644
index 0000000..a16accf
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/clientgen/errors.py
@@ -0,0 +1,245 @@
+from pathlib import Path
+
+from anchorpy_core.idl import Idl, IdlErrorCode
+from autoflake import fix_code
+from black import FileMode, format_str
+from genpy import (
+ Assign,
+ Collection,
+ FromImport,
+ If,
+ Import,
+ Return,
+ Statement,
+ Suite,
+)
+from genpy import Function as UntypedFunction
+
+from anchorpy.clientgen.common import _sanitize
+from anchorpy.clientgen.genpy_extension import (
+ Class,
+ Function,
+ InitMethod,
+ IntDict,
+ IntDictEntry,
+ TypedParam,
+ Union,
+)
+from anchorpy.error import LangErrorMessage, _LangErrorCode
+
+
+def gen_from_code_fn(has_custom_errors: bool) -> Function:
+ from_code_body = Return(
+ "custom.from_code(code) if code >= 6000 else anchor.from_code(code)"
+ if has_custom_errors
+ else "anchor.from_code(code)"
+ )
+ from_code_return_type = (
+ Union(["custom.CustomError", "anchor.AnchorError", "None"])
+ if has_custom_errors
+ else "typing.Optional[anchor.AnchorError]"
+ )
+ return Function(
+ "from_code",
+ [TypedParam("code", "int")],
+ from_code_body,
+ str(from_code_return_type),
+ )
+
+
+def gen_from_tx_error_fn(has_custom_errors: bool) -> Function:
+ err_info_assign = Assign("err_info", "error.args[0]")
+ err_code_assign = Assign("extracted", "extract_code_and_logs(err_info, PROGRAM_ID)")
+ null_code_check = If("extracted is None", Return(None))
+ final_return = Return("from_code(extracted[0])")
+ fn_body = Suite(
+ [
+ err_info_assign,
+ err_code_assign,
+ null_code_check,
+ final_return,
+ ]
+ )
+ return_type = (
+ "typing.Union[anchor.AnchorError, custom.CustomError, None]"
+ if has_custom_errors
+ else "typing.Optional[anchor.AnchorError]"
+ )
+ return Function(
+ "from_tx_error",
+ [TypedParam("error", "RPCException")],
+ fn_body,
+ return_type,
+ )
+
+
+def gen_custom_errors_code(errors: list[IdlErrorCode]) -> str:
+ typing_import = Import("typing")
+ error_import = FromImport(
+ "anchorpy.error", ["ProgramError", "extract_code_and_logs"]
+ )
+ error_names: list[str] = []
+ classes: list[Class] = []
+ error_map_entries: list[IntDictEntry] = []
+ for error in errors:
+ code = error.code
+ name = _sanitize(error.name)
+ maybe_msg = error.msg
+ msg = None if maybe_msg is None else f'"{maybe_msg}"'
+ init_body = Statement(f"super().__init__({code}, {msg})")
+ attrs = [
+ InitMethod([], init_body),
+ Assign("code", code),
+ Assign("name", f'"{name}"'),
+ Assign("msg", msg),
+ ]
+ klass = Class(name=name, bases=["ProgramError"], attributes=attrs)
+ classes.append(klass)
+ error_names.append(name)
+ error_map_entries.append(IntDictEntry(code, f"{name}()"))
+ type_alias = Assign("CustomError", Union(error_names))
+ error_map = Assign(
+ "CUSTOM_ERROR_MAP: dict[int, CustomError]", IntDict(error_map_entries)
+ )
+ from_code_body = Suite(
+ [
+ Assign("maybe_err", "CUSTOM_ERROR_MAP.get(code)"),
+ If("maybe_err is None", Return("None")),
+ Return("maybe_err"),
+ ]
+ )
+ from_code_fn = Function(
+ "from_code",
+ [TypedParam("code", "int")],
+ from_code_body,
+ "typing.Optional[CustomError]",
+ )
+ return str(
+ Collection(
+ [typing_import, error_import, *classes, type_alias, error_map, from_code_fn]
+ )
+ )
+
+
+def gen_custom_errors(idl: Idl, errors_dir: Path) -> None:
+ errors = idl.errors
+ if errors is None or not errors:
+ return
+ code = gen_custom_errors_code(errors)
+ formatted = format_str(code, mode=FileMode())
+ fixed = fix_code(formatted, remove_all_unused_imports=True)
+ (errors_dir / "custom.py").with_suffix(".py").write_text(fixed)
+
+
+def gen_anchor_errors_code() -> str:
+ typing_import = Import("typing")
+ error_import = FromImport("anchorpy.error", ["ProgramError"])
+ error_names: list[str] = []
+ classes: list[Class] = []
+ error_map_entries: list[IntDictEntry] = []
+ for variant in _LangErrorCode:
+ name = _sanitize(variant.name)
+ code = variant.value
+ maybe_msg = LangErrorMessage.get(variant)
+ msg = None if maybe_msg is None else f'"{maybe_msg}"'
+ init_body = Statement(f"super().__init__({code}, {msg})")
+ attrs = [
+ UntypedFunction("__init__", ["self"], init_body),
+ Assign("code", code),
+ Assign("name", f'"{name}"'),
+ Assign("msg", msg),
+ ]
+ klass = Class(name=name, bases=["ProgramError"], attributes=attrs)
+ classes.append(klass)
+ error_names.append(name)
+ error_map_entries.append(IntDictEntry(code, f"{name}()"))
+ type_alias = Assign("AnchorError", Union(error_names))
+ error_map = Assign(
+ "ANCHOR_ERROR_MAP: dict[int, AnchorError]",
+ IntDict(error_map_entries),
+ )
+ from_code_body = Suite(
+ [
+ Assign("maybe_err", "ANCHOR_ERROR_MAP.get(code)"),
+ If("maybe_err is None", Return("None")),
+ Return("maybe_err"),
+ ]
+ )
+ from_code_fn = Function(
+ "from_code",
+ [TypedParam("code", "int")],
+ from_code_body,
+ "typing.Optional[AnchorError]",
+ )
+ return str(
+ Collection(
+ [typing_import, error_import, *classes, type_alias, error_map, from_code_fn]
+ )
+ )
+
+
+def gen_anchor_errors(errors_dir: Path) -> None:
+ code = gen_anchor_errors_code()
+ formatted = format_str(code, mode=FileMode())
+ (errors_dir / "anchor").with_suffix(".py").write_text(formatted)
+
+
+def gen_index_code(idl: Idl) -> str:
+ has_custom_errors = bool(idl.errors)
+ typing_import = Import("typing")
+ rpc_exception_import = FromImport("solana.rpc.core", ["RPCException"])
+ tx_status_import = FromImport(
+ "solders.transaction_status",
+ ["InstructionErrorCustom", "TransactionErrorInstructionError"],
+ )
+ preflight_error_import = FromImport(
+ "solders.rpc.errors", ["SendTransactionPreflightFailureMessage"]
+ )
+ extract_code_and_logs_import = FromImport(
+ "anchorpy.error", ["extract_code_and_logs"]
+ )
+ program_id_import = FromImport("..program_id", ["PROGRAM_ID"])
+ anchor_import = FromImport(".", ["anchor"])
+ re_import = Import("re")
+ base_import_lines = [
+ typing_import,
+ re_import,
+ tx_status_import,
+ rpc_exception_import,
+ preflight_error_import,
+ extract_code_and_logs_import,
+ program_id_import,
+ anchor_import,
+ ]
+ custom_import_lines = [FromImport(".", ["custom"])] if has_custom_errors else []
+ import_lines = base_import_lines + custom_import_lines
+ from_code_fn = gen_from_code_fn(has_custom_errors)
+ error_re_line = Assign(
+ "error_re", r're.compile(r"Program (\w+) failed: custom program error: (\w+)")'
+ )
+ from_tx_error_fn = gen_from_tx_error_fn(has_custom_errors)
+ return str(
+ Collection(
+ [
+ *import_lines,
+ from_code_fn,
+ error_re_line,
+ from_tx_error_fn,
+ ]
+ )
+ )
+
+
+def gen_index_file(idl: Idl, errors_dir: Path) -> None:
+ code = gen_index_code(idl)
+ path = errors_dir / "__init__.py"
+ formatted = format_str(code, mode=FileMode())
+ path.write_text(formatted)
+
+
+def gen_errors(idl: Idl, root: Path) -> None:
+ errors_dir = root / "errors"
+ errors_dir.mkdir(exist_ok=True)
+ gen_index_file(idl, errors_dir)
+ gen_custom_errors(idl, errors_dir)
+ gen_anchor_errors(errors_dir)
diff --git a/basics/anchorpy-main/src/anchorpy/clientgen/genpy_extension.py b/basics/anchorpy-main/src/anchorpy/clientgen/genpy_extension.py
new file mode 100644
index 0000000..40c140a
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/clientgen/genpy_extension.py
@@ -0,0 +1,239 @@
+from typing import Iterator, Optional
+from typing import Union as TypingUnion
+
+from genpy import (
+ Assign,
+ FromImport,
+ Generable,
+ Suite,
+)
+from genpy import Class as BrokenClass
+from genpy import Function as FunctionOriginal
+
+
+class Class(BrokenClass):
+ def generate(self) -> Iterator[str]:
+ bases = self.bases
+ if not bases:
+ bases = []
+
+ yield "class {}({}):".format(self.name, ", ".join(bases))
+ if self.attributes:
+ for f in self.attributes:
+ yield from (" " + f_line for f_line in f.generate())
+ else:
+ yield " pass"
+
+
+class TypedParam(Generable):
+ def __init__(self, name: str, type_: Optional[str]) -> None:
+ self.name = name
+ self.type = type_
+
+ def generate(self) -> Iterator[str]:
+ if self.type is None:
+ yield self.name
+ else:
+ yield f"{self.name}: {self.type}"
+
+
+class Break(Generable):
+ def generate(self):
+ yield "break"
+
+
+class Continue(Generable):
+ def generate(self):
+ yield "continue"
+
+
+class Union(Generable):
+ def __init__(self, members: list[str]) -> None:
+ self.members = members
+
+ def generate(self) -> Iterator[str]:
+ joined = ",".join(self.members)
+ yield f"typing.Union[{joined}]"
+
+
+class Tuple(Generable):
+ def __init__(self, members: list[str]) -> None:
+ self.members = members
+
+ def generate(self) -> Iterator[str]:
+ joined = ",".join(self.members)
+ yield f"({joined},)"
+
+
+class List(Generable):
+ def __init__(self, members: list[str]) -> None:
+ self.members = members
+
+ def generate(self) -> Iterator[str]:
+ joined = ",".join(self.members)
+ yield f"[{joined}]"
+
+
+class TupleTypeAlias(Generable):
+ def __init__(self, name: str, members: list[str]) -> None:
+ self.name = name
+ self.members = members
+
+ def generate(self) -> Iterator[str]:
+ yield str(Assign(self.name, f"tuple{List(self.members)}"))
+
+
+class StrDictEntry(Generable):
+ def __init__(self, key: str, val: TypingUnion[str, "StrDict"]) -> None:
+ self.key = key
+ self.val = val
+
+ def generate(self) -> Iterator[str]:
+ yield f'"{self.key}": {self.val},'
+
+
+class NamedArg(Generable):
+ def __init__(self, key: str, val: str) -> None:
+ self.key = key
+ self.val = val
+
+ def generate(self) -> Iterator[str]:
+ yield f"{self.key}={self.val},"
+
+
+class Call(Generable):
+ def __init__(self, func: str, args: list[NamedArg]) -> None:
+ self.func = func
+ self.args = args
+
+ def generate(self) -> Iterator[str]:
+ formatted_args = "".join(str(arg) for arg in self.args)
+ yield f"{self.func}({formatted_args})"
+
+
+class StrDict(Generable):
+ def __init__(self, items: list[StrDictEntry]) -> None:
+ self.items = items
+
+ def generate(self) -> Iterator[str]:
+ formatted_items = "".join(str(item) for item in self.items)
+ yield "{" + formatted_items + "}"
+
+
+class IntDictEntry(Generable):
+ def __init__(self, key: int, val: str) -> None:
+ self.key = key
+ self.val = val
+
+ def generate(self) -> Iterator[str]:
+ yield f"{self.key}: {self.val},"
+
+
+class IntDict(Generable):
+ def __init__(self, items: list[IntDictEntry]) -> None:
+ self.items = items
+
+ def generate(self) -> Iterator[str]:
+ formatted_items = "".join(str(item) for item in self.items)
+ yield "{" + formatted_items + "}"
+
+
+class Function(FunctionOriginal):
+ def __init__(
+ self,
+ name: str,
+ args: list[TypedParam],
+ body: Generable,
+ return_type: str,
+ decorators: tuple[str, ...] = (),
+ is_async: bool = False,
+ ) -> None:
+ super().__init__(name, args, body, decorators)
+ self.return_type = return_type
+ self.is_async = is_async
+
+ def generate(self) -> Iterator[str]:
+ yield from self.decorators
+ arg_strings = []
+ for arg in self.args:
+ annotation = "" if arg.type is None else f": {arg.type}"
+ arg_strings.append(f"{arg.name}{annotation}")
+ def_base = "async def" if self.is_async else "def"
+ yield "{} {}({}) -> {}:".format(
+ def_base, self.name, ", ".join(arg_strings), self.return_type
+ )
+ yield from self.body.generate()
+
+
+class StaticMethod(Function):
+ def __init__(
+ self, name: str, args: list[TypedParam], body: Generable, return_type: str
+ ) -> None:
+ super().__init__(name, args, body, return_type, ("@staticmethod",))
+
+
+class ClassMethod(Function):
+ def __init__(
+ self,
+ name: str,
+ extra_args: list[TypedParam],
+ body: Generable,
+ return_type: str,
+ is_async: bool = False,
+ ) -> None:
+ args = [TypedParam("cls", None), *extra_args]
+ super().__init__(name, args, body, return_type, ("@classmethod",), is_async)
+
+
+class Method(Function):
+ def __init__(
+ self, name: str, extra_args: list[TypedParam], body: Generable, return_type: str
+ ) -> None:
+ args = [TypedParam("self", None), *extra_args]
+ super().__init__(name, args, body, return_type)
+
+
+class InitMethod(Method):
+ def __init__(self, extra_args: list[TypedParam], body: Generable) -> None:
+ super().__init__("__init__", extra_args, body, "None")
+
+
+class Dataclass(Class):
+ def __init__(
+ self,
+ name,
+ attributes: list[TypingUnion[TypedParam, Assign, ClassMethod, Method]],
+ ) -> None:
+ super().__init__(name, None, attributes)
+
+ def generate(self) -> Iterator[str]:
+ yield "@dataclass"
+ yield from super().generate()
+
+
+class TypedDict(Class):
+ def __init__(self, name, params: list[TypedParam]) -> None:
+ super().__init__(name, ["typing.TypedDict"], params)
+
+ def generate(self) -> Iterator[str]:
+ yield from super().generate()
+
+
+class Try(Generable):
+ def __init__(self, try_body, to_catch, except_body):
+ if not isinstance(try_body, Suite):
+ try_body = Suite(try_body)
+ if not isinstance(except_body, Suite):
+ except_body = Suite(except_body)
+ self.try_body = try_body
+ self.to_catch = to_catch
+ self.except_body = except_body
+
+ def generate(self):
+ yield "try:"
+ yield from self.try_body.generate()
+ yield f"except {self.to_catch}:"
+ yield from self.except_body.generate()
+
+
+ANNOTATIONS_IMPORT = FromImport("__future__", ["annotations"])
diff --git a/basics/anchorpy-main/src/anchorpy/clientgen/instructions.py b/basics/anchorpy-main/src/anchorpy/clientgen/instructions.py
new file mode 100644
index 0000000..7c47eea
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/clientgen/instructions.py
@@ -0,0 +1,363 @@
+from pathlib import Path
+from typing import Optional, Union, cast
+
+from anchorpy_core.idl import (
+ Idl,
+ IdlAccountItem,
+ IdlAccounts,
+ IdlSeedConst,
+ IdlTypeArray,
+ IdlTypeSimple,
+)
+from autoflake import fix_code
+from black import FileMode, format_str
+from genpy import (
+ Assign,
+ Collection,
+ FromImport,
+ If,
+ Import,
+ ImportAs,
+ Line,
+ Return,
+ Suite,
+)
+from pyheck import shouty_snake, snake, upper_camel
+
+from anchorpy.clientgen.common import (
+ _field_to_encodable,
+ _layout_for_type,
+ _py_type_from_idl,
+ _sanitize,
+)
+from anchorpy.clientgen.genpy_extension import (
+ ANNOTATIONS_IMPORT,
+ Call,
+ Function,
+ List,
+ NamedArg,
+ StrDict,
+ StrDictEntry,
+ TypedDict,
+ TypedParam,
+)
+from anchorpy.coder.common import _sighash
+from anchorpy.coder.idl import FIELD_TYPE_MAP
+
+CONST_ACCOUNTS = {
+ "associated_token_program": "ASSOCIATED_TOKEN_PROGRAM_ID",
+ "rent": "RENT",
+ "system_program": "SYS_PROGRAM_ID",
+ "token_program": "TOKEN_PROGRAM_ID",
+ "clock": "CLOCK",
+}
+
+
+def gen_instructions(idl: Idl, root: Path, gen_pdas: bool) -> None:
+ instructions_dir = root / "instructions"
+ instructions_dir.mkdir(exist_ok=True)
+ gen_index_file(idl, instructions_dir)
+ instructions = gen_instructions_code(idl, instructions_dir, gen_pdas)
+ for path, code in instructions.items():
+ formatted = format_str(code, mode=FileMode())
+ fixed = fix_code(formatted, remove_all_unused_imports=True)
+ path.write_text(fixed)
+
+
+def gen_index_file(idl: Idl, instructions_dir: Path) -> None:
+ code = gen_index_code(idl)
+ path = instructions_dir / "__init__.py"
+ formatted = format_str(code, mode=FileMode())
+ path.write_text(formatted)
+
+
+def gen_index_code(idl: Idl) -> str:
+ imports: list[FromImport] = []
+ for ix in idl.instructions:
+ ix_name_snake_unsanitized = snake(ix.name)
+ ix_name = _sanitize(ix_name_snake_unsanitized)
+ import_members: list[str] = [ix_name]
+ if ix.args:
+ import_members.append(_args_interface_name(ix_name_snake_unsanitized))
+ if ix.accounts:
+ import_members.append(_accounts_interface_name(ix_name_snake_unsanitized))
+ if import_members:
+ imports.append(FromImport(f".{ix_name}", import_members))
+ return str(Collection(imports))
+
+
+def _args_interface_name(ix_name: str) -> str:
+ return f"{upper_camel(ix_name)}Args"
+
+
+def _accounts_interface_name(ix_name: str) -> str:
+ return f"{upper_camel(ix_name)}Accounts"
+
+
+def recurse_accounts(
+ accs: list[IdlAccountItem],
+ nested_names: list[str],
+ const_accs: dict[int, str],
+ acc_idx: int = 0,
+) -> tuple[list[str], int]:
+ elements: list[str] = []
+ for acc in accs:
+ names = [*nested_names, _sanitize(snake(acc.name))]
+ if isinstance(acc, IdlAccounts):
+ nested_accs = cast(IdlAccounts, acc)
+ new_elements, acc_idx = recurse_accounts(
+ nested_accs.accounts, names, const_accs, acc_idx
+ )
+ elements.extend(new_elements)
+ else:
+ acc_idx += 1
+ try:
+ pubkey_var = const_accs[acc_idx]
+ except KeyError:
+ try:
+ pubkey_var = CONST_ACCOUNTS[names[-1]]
+ except KeyError:
+ nested_keys = [f'["{key}"]' for key in names]
+ dict_accessor = "".join(nested_keys)
+ pubkey_var = f"accounts{dict_accessor}"
+ if acc.is_optional:
+ elements.append(
+ f"AccountMeta(pubkey={pubkey_var}, "
+ f"is_signer={acc.is_signer}, "
+ f"is_writable={acc.is_mut}) "
+ f"if {pubkey_var} else "
+ f"AccountMeta(pubkey=program_id, "
+ f"is_signer=False, is_writable=False)"
+ )
+ else:
+ elements.append(
+ f"AccountMeta(pubkey={pubkey_var}, "
+ f"is_signer={acc.is_signer}, "
+ f"is_writable={acc.is_mut})"
+ )
+ return elements, acc_idx
+
+
+def to_buffer_value(
+ ty: Union[IdlTypeSimple, IdlTypeArray], value: Union[str, int, list[int]]
+) -> bytes:
+ if isinstance(value, int):
+ encoder = FIELD_TYPE_MAP[cast(IdlTypeSimple, ty)]
+ return encoder.build(value)
+ if isinstance(value, str):
+ return value.encode()
+ if isinstance(value, list):
+ return bytes(value)
+ raise ValueError(f"Unexpected type. ty: {ty}; value: {value}")
+
+
+GenAccountsRes = tuple[list[TypedDict], list[Assign], dict[int, str], int]
+
+
+def gen_accounts(
+ name,
+ idl_accs: list[IdlAccountItem],
+ gen_pdas: bool,
+ accum: Optional[GenAccountsRes] = None,
+) -> GenAccountsRes:
+ if accum is None:
+ extra_typeddicts_to_use: list[TypedDict] = []
+ accum_const_pdas: list[Assign] = []
+ const_acc_indices: dict[int, str] = {}
+ acc_count = 0
+ else:
+ extra_typeddicts_to_use, accum_const_pdas, const_acc_indices, acc_count = accum
+ params: list[TypedParam] = []
+ const_pdas: list[Assign] = []
+ for acc in idl_accs:
+ acc_name = _sanitize(snake(acc.name))
+ if isinstance(acc, IdlAccounts):
+ nested_accs = cast(IdlAccounts, acc)
+ nested_acc_name = f"{upper_camel(nested_accs.name)}Nested"
+ nested_res = gen_accounts(
+ nested_acc_name,
+ nested_accs.accounts,
+ gen_pdas,
+ (
+ extra_typeddicts_to_use,
+ accum_const_pdas,
+ const_acc_indices,
+ acc_count,
+ ),
+ )
+ if nested_res[0]:
+ params.append(TypedParam(acc_name, f"{nested_acc_name}"))
+ extra_typeddicts_to_use = extra_typeddicts_to_use + nested_res[0]
+ accum_const_pdas = accum_const_pdas + nested_res[1]
+ const_acc_indices = const_acc_indices | nested_res[2]
+ acc_count = nested_res[3] + 1
+ else:
+ acc_count += 1
+ pda_generated = False
+ if gen_pdas:
+ maybe_pda = acc.pda
+ if maybe_pda is not None and all(
+ isinstance(seed, IdlSeedConst) for seed in maybe_pda.seeds
+ ):
+ seeds = cast(list[IdlSeedConst], maybe_pda.seeds)
+ const_pda_name = shouty_snake(f"{name}_{acc_name}")
+ const_pda_body_items = [
+ str(
+ to_buffer_value(
+ cast(Union[IdlTypeSimple, IdlTypeArray], seed.ty),
+ cast(Union[str, int, list[int]], seed.value),
+ )
+ )
+ for seed in seeds
+ ]
+ seeds_arg = List(const_pda_body_items)
+ seeds_named_arg = NamedArg("seeds", seeds_arg)
+ const_pda_body = Call(
+ "Pubkey.find_program_address",
+ [seeds_named_arg, NamedArg("program_id", "PROGRAM_ID")],
+ )
+ const_pdas.append(Assign(const_pda_name, f"{const_pda_body}[0]"))
+ const_acc_indices = {
+ **const_acc_indices,
+ acc_count: const_pda_name,
+ }
+ pda_generated = True
+ if not pda_generated:
+ try:
+ CONST_ACCOUNTS[acc_name]
+ except KeyError:
+ if acc.is_optional:
+ params.append(TypedParam(acc_name, "typing.Optional[Pubkey]"))
+ else:
+ params.append(TypedParam(acc_name, "Pubkey"))
+ maybe_typed_dict_container = [TypedDict(name, params)] if params else []
+ accounts = maybe_typed_dict_container + extra_typeddicts_to_use
+ return accounts, accum_const_pdas + const_pdas, const_acc_indices, acc_count
+
+
+def gen_instructions_code(idl: Idl, out: Path, gen_pdas: bool) -> dict[Path, str]:
+ types_import = [FromImport("..", ["types"])] if idl.types else []
+ imports = [
+ ANNOTATIONS_IMPORT,
+ Import("typing"),
+ FromImport("solders.pubkey", ["Pubkey"]),
+ FromImport("solders.system_program", ["ID as SYS_PROGRAM_ID"]),
+ FromImport("solders.sysvar", ["RENT", "CLOCK"]),
+ FromImport(
+ "spl.token.constants", ["TOKEN_PROGRAM_ID", "ASSOCIATED_TOKEN_PROGRAM_ID"]
+ ),
+ FromImport("solders.instruction", ["Instruction", "AccountMeta"]),
+ FromImport(
+ "anchorpy.borsh_extension", ["BorshPubkey", "EnumForCodegen", "COption"]
+ ),
+ FromImport("construct", ["Pass", "Construct"]),
+ ImportAs("borsh_construct", "borsh"),
+ *types_import,
+ FromImport("..program_id", ["PROGRAM_ID"]),
+ ]
+ result = {}
+ for ix in idl.instructions:
+ ix_name_snake_unsanitized = snake(ix.name)
+ ix_name = _sanitize(ix_name_snake_unsanitized)
+ filename = (out / ix_name).with_suffix(".py")
+ args_interface_params: list[TypedParam] = []
+ layout_items: list[str] = []
+ encoded_args_entries: list[StrDictEntry] = []
+ accounts_interface_name = _accounts_interface_name(ix_name_snake_unsanitized)
+ for arg in ix.args:
+ arg_name = _sanitize(snake(arg.name))
+ args_interface_params.append(
+ TypedParam(
+ arg_name,
+ _py_type_from_idl(
+ idl=idl,
+ ty=arg.ty,
+ types_relative_imports=False,
+ use_fields_interface_for_struct=False,
+ ),
+ )
+ )
+ layout_items.append(
+ _layout_for_type(
+ idl=idl, ty=arg.ty, name=arg_name, types_relative_imports=False
+ )
+ )
+ encoded_args_entries.append(
+ StrDictEntry(
+ arg_name,
+ _field_to_encodable(
+ idl=idl,
+ ty=arg,
+ types_relative_imports=False,
+ val_prefix='args["',
+ val_suffix='"]',
+ ),
+ )
+ )
+ if ix.args:
+ args_interface_name = _args_interface_name(ix_name)
+ args_interface_container = [
+ TypedDict(args_interface_name, args_interface_params)
+ ]
+ layout_val = f"borsh.CStruct({','.join(layout_items)})"
+ layout_assignment_container = [Assign("layout", layout_val)]
+ args_container = [TypedParam("args", args_interface_name)]
+ encoded_args_val = f"layout.build({StrDict(encoded_args_entries)})"
+ else:
+ args_interface_container = []
+ layout_val = "Pass"
+ args_container = []
+ layout_assignment_container = []
+ encoded_args_val = 'b""'
+ accounts_container = (
+ [TypedParam("accounts", accounts_interface_name)] if ix.accounts else []
+ )
+ accounts, const_pdas, const_acc_indices, _ = gen_accounts(
+ accounts_interface_name, ix.accounts, gen_pdas
+ )
+ recursed = recurse_accounts(ix.accounts, [], const_acc_indices)[0]
+ keys_assignment = Assign("keys: list[AccountMeta]", f"{List(recursed)}")
+ remaining_accounts_concatenation = If(
+ "remaining_accounts is not None", Line("keys += remaining_accounts")
+ )
+ identifier_assignment = Assign(
+ "identifier", _sighash(ix_name_snake_unsanitized)
+ )
+ encoded_args_assignment = Assign("encoded_args", encoded_args_val)
+ data_assignment = Assign("data", "identifier + encoded_args")
+ returning = Return("Instruction(program_id, data, keys)")
+ ix_fn = Function(
+ ix_name,
+ [
+ *args_container,
+ *accounts_container,
+ TypedParam("program_id", "Pubkey = PROGRAM_ID"),
+ TypedParam(
+ "remaining_accounts",
+ "typing.Optional[typing.List[AccountMeta]] = None",
+ ),
+ ],
+ Suite(
+ [
+ keys_assignment,
+ remaining_accounts_concatenation,
+ identifier_assignment,
+ encoded_args_assignment,
+ data_assignment,
+ returning,
+ ]
+ ),
+ "Instruction",
+ )
+ contents = Collection(
+ [
+ *imports,
+ *args_interface_container,
+ *layout_assignment_container,
+ *const_pdas,
+ *accounts,
+ ix_fn,
+ ]
+ )
+ result[filename] = str(contents)
+ return result
diff --git a/basics/anchorpy-main/src/anchorpy/clientgen/program_id.py b/basics/anchorpy-main/src/anchorpy/clientgen/program_id.py
new file mode 100644
index 0000000..770aafe
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/clientgen/program_id.py
@@ -0,0 +1,16 @@
+from pathlib import Path
+
+from black import FileMode, format_str
+from genpy import Assign, Collection, FromImport
+
+
+def gen_program_id_code(program_id: str) -> str:
+ import_line = FromImport("solders.pubkey", ["Pubkey"])
+ assignment_line = Assign("PROGRAM_ID", f'Pubkey.from_string("{program_id}")')
+ return str(Collection([import_line, assignment_line]))
+
+
+def gen_program_id(program_id: str, root: Path) -> None:
+ code = gen_program_id_code(program_id)
+ formatted = format_str(code, mode=FileMode())
+ (root / "program_id.py").write_text(formatted)
diff --git a/basics/anchorpy-main/src/anchorpy/clientgen/types.py b/basics/anchorpy-main/src/anchorpy/clientgen/types.py
new file mode 100644
index 0000000..fa70033
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/clientgen/types.py
@@ -0,0 +1,623 @@
+from dataclasses import dataclass
+from pathlib import Path
+from typing import Union as TypingUnion
+from typing import cast
+
+from anchorpy_core.idl import (
+ Idl,
+ IdlEnumVariant,
+ IdlField,
+ IdlType,
+ IdlTypeDefinitionTyStruct,
+)
+from autoflake import fix_code
+from black import FileMode, format_str
+from genpy import (
+ Assign,
+ Collection,
+ FromImport,
+ Generable,
+ If,
+ Import,
+ ImportAs,
+ Raise,
+ Return,
+ Suite,
+)
+from pyheck import snake
+
+from anchorpy.clientgen.common import (
+ _field_from_decoded,
+ _field_from_json,
+ _field_to_encodable,
+ _field_to_json,
+ _idl_type_to_json_type,
+ _json_interface_name,
+ _kind_interface_name,
+ _layout_for_type,
+ _py_type_from_idl,
+ _sanitize,
+ _value_interface_name,
+)
+from anchorpy.clientgen.genpy_extension import (
+ ANNOTATIONS_IMPORT,
+ Call,
+ ClassMethod,
+ Dataclass,
+ Function,
+ Method,
+ NamedArg,
+ StrDict,
+ StrDictEntry,
+ Tuple,
+ TupleTypeAlias,
+ TypedDict,
+ TypedParam,
+ Union,
+)
+
+
+def gen_types(idl: Idl, root: Path) -> None:
+ types = idl.types
+ if types is None or not types:
+ return
+ types_dir = root / "types"
+ types_dir.mkdir(exist_ok=True)
+ gen_index_file(idl, types_dir)
+ gen_type_files(idl, types_dir)
+
+
+def gen_index_file(idl: Idl, types_dir: Path) -> None:
+ code = gen_index_code(idl)
+ path = types_dir / "__init__.py"
+ formatted = format_str(code, mode=FileMode())
+ path.write_text(formatted)
+
+
+def gen_index_code(idl: Idl) -> str:
+ imports: list[TypingUnion[Import, FromImport]] = [Import("typing")]
+ for ty in idl.types:
+ ty_type = ty.ty
+ module_name = _sanitize(snake(ty.name))
+ imports.append(FromImport(".", [module_name]))
+ import_members = (
+ [_sanitize(ty.name), _json_interface_name(ty.name)]
+ if isinstance(ty_type, IdlTypeDefinitionTyStruct)
+ else [_kind_interface_name(ty.name), _json_interface_name(ty.name)]
+ )
+ imports.append(
+ FromImport(
+ f".{module_name}",
+ import_members,
+ )
+ )
+ return str(Collection(imports))
+
+
+def gen_type_files(idl: Idl, types_dir: Path) -> None:
+ types_code = gen_types_code(idl, types_dir)
+ for path, code in types_code.items():
+ formatted = format_str(code, mode=FileMode())
+ fixed = fix_code(formatted, remove_all_unused_imports=True)
+ path.write_text(fixed)
+
+
+def gen_types_code(idl: Idl, out: Path) -> dict[Path, str]:
+ res = {}
+ types_module_names = [_sanitize(snake(ty.name)) for ty in idl.types]
+ for ty in idl.types:
+ ty_name = _sanitize(ty.name)
+ module_name = _sanitize(snake(ty.name))
+ relative_import_items = [
+ mod for mod in types_module_names if mod != module_name
+ ]
+ relative_import_container = (
+ [FromImport(".", relative_import_items)] if relative_import_items else []
+ )
+ ty_type = ty.ty
+ body = (
+ gen_struct(idl, ty_name, ty_type.fields)
+ if isinstance(ty_type, IdlTypeDefinitionTyStruct)
+ else gen_enum(idl, ty_name, ty_type.variants)
+ )
+ code = str(Collection([ANNOTATIONS_IMPORT, *relative_import_container, body]))
+ path = (out / module_name).with_suffix(".py")
+ res[path] = code
+ return res
+
+
+def gen_struct(idl: Idl, name: str, fields: list[IdlField]) -> Collection:
+ imports = [
+ Import("typing"),
+ FromImport("dataclasses", ["dataclass"]),
+ FromImport("construct", ["Container", "Construct"]),
+ FromImport("solders.pubkey", ["Pubkey"]),
+ FromImport("anchorpy.borsh_extension", ["BorshPubkey"]),
+ ImportAs("borsh_construct", "borsh"),
+ ]
+ json_interface_name = _json_interface_name(name)
+ field_params: list[TypedParam] = []
+ json_interface_params: list[TypedParam] = []
+ layout_items: list[str] = []
+ from_decoded_items: list[str] = []
+ to_encodable_items: list[str] = []
+ to_json_items: list[str] = []
+ from_json_items: list[str] = []
+ for field in fields:
+ field_name = _sanitize(snake(field.name))
+ field_params.append(
+ TypedParam(
+ field_name,
+ _py_type_from_idl(
+ idl=idl,
+ ty=field.ty,
+ types_relative_imports=True,
+ use_fields_interface_for_struct=False,
+ ),
+ )
+ )
+ json_interface_params.append(
+ TypedParam(
+ field_name,
+ _idl_type_to_json_type(ty=field.ty, types_relative_imports=True),
+ )
+ )
+ layout_items.append(
+ _layout_for_type(
+ idl=idl, ty=field.ty, name=field_name, types_relative_imports=True
+ )
+ )
+ from_decoded_item_val = _field_from_decoded(
+ idl=idl,
+ ty=IdlField(name=snake(field.name), docs=None, ty=field.ty),
+ val_prefix="obj.",
+ types_relative_imports=True,
+ )
+ from_decoded_items.append(f"{field_name}={from_decoded_item_val}")
+ as_encodable = _field_to_encodable(
+ idl=idl,
+ ty=field,
+ val_prefix="self.",
+ val_suffix="",
+ types_relative_imports=True,
+ )
+ to_encodable_items.append(f'"{field_name}": {as_encodable}')
+ to_json_items.append(f'"{field_name}": {_field_to_json(idl, field, "self.")}')
+ field_from_json = _field_from_json(
+ idl=idl, ty=field, types_relative_imports=True
+ )
+ from_json_items.append(f"{field_name}={field_from_json}")
+ json_interface = TypedDict(json_interface_name, json_interface_params)
+ layout = f"borsh.CStruct({','.join(layout_items)})"
+ args_for_from_decoded = ",".join(from_decoded_items)
+ to_encodable_body = "{" + ",".join(to_encodable_items) + "}"
+ to_json_body = "{" + ",".join(to_json_items) + "}"
+ args_for_from_json = ",".join(from_json_items)
+ struct_cls = Dataclass(
+ name,
+ [
+ Assign("layout: typing.ClassVar", layout),
+ *field_params,
+ ClassMethod(
+ "from_decoded",
+ [TypedParam("obj", "Container")],
+ Return(f"cls({args_for_from_decoded})"),
+ f'"{name}"',
+ ),
+ Method(
+ "to_encodable",
+ [],
+ Return(to_encodable_body),
+ "dict[str, typing.Any]",
+ ),
+ Method("to_json", [], Return(to_json_body), json_interface_name),
+ ClassMethod(
+ "from_json",
+ [TypedParam("obj", json_interface_name)],
+ Return(f"cls({args_for_from_json})"),
+ f'"{name}"',
+ ),
+ ],
+ )
+ return Collection([*imports, json_interface, struct_cls])
+
+
+def _make_cstruct(fields: dict[str, str]) -> str:
+ formatted_fields = ",".join([f'"{key}" / {val}' for key, val in fields.items()])
+ return f"borsh.CStruct({formatted_fields})"
+
+
+@dataclass
+class _NamedFieldRecord:
+ field_type_alias_entry: TypedParam
+ value_type_alias_entry: TypedParam
+ json_interface_value_type_entry: TypedParam
+ json_value_item: StrDictEntry
+ encodable_value_item: StrDictEntry
+ init_entry_for_from_decoded: NamedArg
+ init_entry_for_from_json: NamedArg
+
+
+def _make_named_field_record(
+ named_field: IdlField, idl: Idl, cast_obj_var_name: str
+) -> _NamedFieldRecord:
+ named_field_name = _sanitize(snake(named_field.name))
+ return _NamedFieldRecord(
+ field_type_alias_entry=TypedParam(
+ named_field_name,
+ _py_type_from_idl(
+ idl=idl,
+ ty=named_field.ty,
+ types_relative_imports=True,
+ use_fields_interface_for_struct=False,
+ ),
+ ),
+ value_type_alias_entry=TypedParam(
+ named_field_name,
+ _py_type_from_idl(
+ idl=idl,
+ ty=named_field.ty,
+ types_relative_imports=True,
+ use_fields_interface_for_struct=False,
+ ),
+ ),
+ json_interface_value_type_entry=TypedParam(
+ named_field_name,
+ _idl_type_to_json_type(ty=named_field.ty, types_relative_imports=True),
+ ),
+ json_value_item=StrDictEntry(
+ named_field_name,
+ _field_to_json(idl, named_field, 'self.value["', val_suffix='"]'),
+ ),
+ encodable_value_item=StrDictEntry(
+ named_field_name,
+ _field_to_encodable(
+ idl=idl,
+ ty=named_field,
+ val_prefix='self.value["',
+ val_suffix='"]',
+ types_relative_imports=True,
+ ),
+ ),
+ init_entry_for_from_decoded=NamedArg(
+ named_field_name,
+ _field_from_decoded(
+ idl=idl,
+ ty=IdlField(f'val["{named_field_name}"]', docs=None, ty=named_field.ty),
+ types_relative_imports=True,
+ val_prefix="",
+ ),
+ ),
+ init_entry_for_from_json=NamedArg(
+ named_field_name,
+ _field_from_json(
+ idl=idl,
+ ty=named_field,
+ param_prefix=f'{cast_obj_var_name}["',
+ param_suffix='"]',
+ types_relative_imports=True,
+ ),
+ ),
+ )
+
+
+@dataclass
+class _UnnamedFieldRecord:
+ field_type_alias_element: str
+ value_type_alias_element: str
+ json_interface_value_element: str
+ json_value_element: str
+ encodable_value_item: StrDictEntry
+ init_element_for_from_decoded: str
+ init_element_for_from_json: str
+
+
+def _make_unnamed_field_record(
+ index: int, unnamed_field: IdlType, idl: Idl, cast_obj_var_name: str
+) -> _UnnamedFieldRecord:
+ elem_name = f"value[{index}]"
+ encodable = _field_to_encodable(
+ idl=idl,
+ ty=IdlField(f"[{index}]", docs=None, ty=unnamed_field),
+ val_prefix="self.value",
+ types_relative_imports=True,
+ convert_case=False,
+ )
+ return _UnnamedFieldRecord(
+ field_type_alias_element=_py_type_from_idl(
+ idl=idl,
+ ty=unnamed_field,
+ types_relative_imports=True,
+ use_fields_interface_for_struct=False,
+ ),
+ value_type_alias_element=_py_type_from_idl(
+ idl=idl,
+ ty=unnamed_field,
+ types_relative_imports=True,
+ use_fields_interface_for_struct=False,
+ ),
+ json_interface_value_element=_idl_type_to_json_type(
+ ty=unnamed_field, types_relative_imports=True
+ ),
+ json_value_element=_field_to_json(
+ idl,
+ IdlField(elem_name, docs=None, ty=unnamed_field),
+ "self.",
+ convert_case=False,
+ ),
+ encodable_value_item=StrDictEntry(f"item_{index}", encodable),
+ init_element_for_from_decoded=_field_from_decoded(
+ idl=idl,
+ ty=IdlField(f'val["item_{index}"]', docs=None, ty=unnamed_field),
+ val_prefix="",
+ types_relative_imports=True,
+ ),
+ init_element_for_from_json=_field_from_json(
+ idl=idl,
+ ty=IdlField(str(index), docs=None, ty=unnamed_field),
+ param_prefix=f"{cast_obj_var_name}[",
+ param_suffix="]",
+ types_relative_imports=True,
+ ),
+ )
+
+
+def gen_enum(idl: Idl, name: str, variants: list[IdlEnumVariant]) -> Collection:
+ imports = [
+ Import("typing"),
+ FromImport("dataclasses", ["dataclass"]),
+ FromImport("solders.pubkey", ["Pubkey"]),
+ FromImport("construct", ["Construct"]),
+ FromImport("anchorpy.borsh_extension", ["EnumForCodegen", "BorshPubkey"]),
+ ImportAs("borsh_construct", "borsh"),
+ ]
+ invalid_enum_raise = Raise('ValueError("Invalid enum object")')
+ from_decoded_dict_check = If("not isinstance(obj, dict)", invalid_enum_raise)
+ variant_name_in_obj_checks: list[Generable] = []
+ obj_kind_checks: list[Generable] = []
+ json_interfaces: list[TypedDict] = []
+ classes: list[Dataclass] = []
+ cstructs: list[str] = []
+ type_variants_members: list[str] = []
+ json_variants_members: list[str] = []
+ json_interface_value_field_types: list[TypingUnion[TypedDict, TupleTypeAlias]] = []
+ value_type_aliases: list[TypingUnion[TypedDict, TupleTypeAlias]] = []
+ for idx, variant in enumerate(variants):
+ discriminator = idx
+ fields = variant.fields
+ variant_name = _sanitize(variant.name)
+ value_interface_name = _value_interface_name(variant.name)
+ json_interface_name = _json_interface_name(variant.name)
+ json_interface_value_type_name = f"{json_interface_name}Value"
+ cast_obj_var_name = snake(json_interface_value_type_name)
+ encodable_value_items: list[StrDictEntry] = []
+ cstruct_fields: dict[str, str] = {}
+ to_json_params_base = NamedArg("kind", f'"{variant.name}"')
+ json_interface_kind_field = TypedParam(
+ "kind", f'typing.Literal["{variant.name}"]'
+ )
+ type_variants_members.append(variant_name)
+ json_variants_members.append(_json_interface_name(variant.name))
+
+ def make_variant_name_in_obj_check(then: Generable) -> Generable:
+ return If(f'"{variant.name}" in obj', then)
+
+ def make_obj_kind_check(return_val: str) -> Generable:
+ accessed = 'obj["kind"]'
+ lhs = f"{accessed} == "
+ cast_obj_assignment_container = (
+ [
+ Assign(
+ cast_obj_var_name,
+ f'typing.cast({json_interface_value_type_name}, obj["value"])',
+ )
+ ]
+ if fields
+ else []
+ )
+ return If(
+ f'{lhs}"{variant.name}"',
+ Suite([*cast_obj_assignment_container, Return(return_val)]),
+ )
+
+ if fields is not None:
+ flds = fields.fields
+ val_line_for_from_decoded = Assign("val", f'obj["{variant.name}"]')
+ if isinstance(flds[0], IdlField):
+ named_enum_fields = cast(list[IdlField], flds)
+ value_type_alias_entries: list[TypedParam] = []
+ json_interface_value_type_entries: list[TypedParam] = []
+ json_value_items: list[StrDictEntry] = []
+ init_entries_for_from_decoded: list[NamedArg] = []
+ init_entries_for_from_json: list[NamedArg] = []
+ for named_field in named_enum_fields:
+ rec = _make_named_field_record(named_field, idl, cast_obj_var_name)
+ value_type_alias_entries.append(rec.value_type_alias_entry)
+ json_interface_value_type_entries.append(
+ rec.json_interface_value_type_entry
+ )
+ json_value_items.append(rec.json_value_item)
+ encodable_value_items.append(rec.encodable_value_item)
+ init_entries_for_from_decoded.append(
+ rec.init_entry_for_from_decoded
+ )
+ init_entries_for_from_json.append(rec.init_entry_for_from_json)
+
+ cstruct_fields[snake(named_field.name)] = _layout_for_type(
+ idl=idl, ty=named_field.ty, types_relative_imports=True
+ )
+ value_type_aliases.append(
+ TypedDict(value_interface_name, value_type_alias_entries)
+ )
+ json_interface_value_field_type = TypedDict(
+ json_interface_value_type_name, json_interface_value_type_entries
+ )
+ json_value_entry = StrDict(json_value_items)
+ to_json_body = Return(
+ Call(
+ json_interface_name,
+ [to_json_params_base, NamedArg("value", str(json_value_entry))],
+ )
+ )
+ init_arg_for_from_decoded = Call(
+ value_interface_name, init_entries_for_from_decoded
+ )
+ init_arg_for_from_json = Call(
+ value_interface_name, init_entries_for_from_json
+ )
+ else:
+ tuple_enum_fields = cast(list[IdlType], flds)
+ field_type_alias_elements: list[str] = []
+ value_type_alias_elements: list[str] = []
+ json_interface_value_elements: list[str] = []
+ json_value_elements: list[str] = []
+ init_elements_for_from_decoded: list[str] = []
+ init_elements_for_from_json: list[str] = []
+ for i, unnamed_field in enumerate(tuple_enum_fields):
+ rec_unnamed = _make_unnamed_field_record(
+ i, unnamed_field, idl, cast_obj_var_name
+ )
+ field_type_alias_elements.append(
+ rec_unnamed.field_type_alias_element
+ )
+ value_type_alias_elements.append(
+ rec_unnamed.value_type_alias_element
+ )
+ json_interface_value_elements.append(
+ rec_unnamed.json_interface_value_element
+ )
+ json_value_elements.append(rec_unnamed.json_value_element)
+ encodable_value_items.append(rec_unnamed.encodable_value_item)
+ init_elements_for_from_decoded.append(
+ rec_unnamed.init_element_for_from_decoded
+ )
+ init_elements_for_from_json.append(
+ rec_unnamed.init_element_for_from_json
+ )
+ cstruct_fields[f"item_{i}"] = _layout_for_type(
+ idl=idl, ty=unnamed_field, types_relative_imports=True
+ )
+ value_type_aliases.append(
+ TupleTypeAlias(
+ value_interface_name,
+ value_type_alias_elements,
+ )
+ )
+ json_interface_value_field_type = TupleTypeAlias(
+ json_interface_value_type_name, json_interface_value_elements
+ )
+ to_json_body = Return(
+ Call(
+ json_interface_name,
+ [
+ to_json_params_base,
+ NamedArg("value", str(Tuple(json_value_elements))),
+ ],
+ )
+ )
+ init_arg_for_from_decoded = Tuple(init_elements_for_from_decoded)
+ init_arg_for_from_json = Tuple(init_elements_for_from_json)
+ value_field_container = [TypedParam("value", value_interface_name)]
+ to_json_method = Method("to_json", [], to_json_body, json_interface_name)
+ encodable_value_entry = StrDict(encodable_value_items)
+ to_encodable_body = Return(
+ StrDict([StrDictEntry(variant.name, encodable_value_entry)])
+ )
+ to_encodable_method = Method("to_encodable", [], to_encodable_body, "dict")
+ json_interface_params = [
+ TypedParam("value", json_interface_value_type_name),
+ json_interface_kind_field,
+ ]
+ json_interface_value_field_types.append(json_interface_value_field_type)
+ variant_name_in_obj_check = make_variant_name_in_obj_check(
+ Suite(
+ [
+ val_line_for_from_decoded,
+ Return(
+ f"{_sanitize(variant.name)}"
+ f"({init_arg_for_from_decoded})"
+ ),
+ ]
+ )
+ )
+ obj_kind_check = make_obj_kind_check(
+ f"{_sanitize(variant.name)}({init_arg_for_from_json})",
+ )
+ else:
+ to_json_method = ClassMethod(
+ "to_json",
+ [],
+ Return(Call(json_interface_name, [to_json_params_base])),
+ json_interface_name,
+ )
+ to_encodable_method = ClassMethod(
+ "to_encodable",
+ [],
+ Return(StrDict([StrDictEntry(variant.name, StrDict([]))])),
+ "dict",
+ )
+ value_field_container = []
+ json_interface_params = [json_interface_kind_field]
+ variant_name_in_obj_check = make_variant_name_in_obj_check(
+ Return(f"{_sanitize(variant.name)}()")
+ )
+ obj_kind_check = make_obj_kind_check(f"{_sanitize(variant.name)}()")
+ json_interfaces.append(TypedDict(json_interface_name, json_interface_params))
+ class_common_attrs = [
+ Assign("discriminator: typing.ClassVar", discriminator),
+ Assign("kind: typing.ClassVar", f'"{variant.name}"'),
+ ]
+
+ attrs = [
+ *class_common_attrs,
+ *value_field_container,
+ to_json_method,
+ to_encodable_method,
+ ]
+ classes.append(Dataclass(_sanitize(variant.name), attrs))
+ variant_name_in_obj_checks.append(variant_name_in_obj_check)
+ obj_kind_checks.append(obj_kind_check)
+ cstructs.append(f'"{variant.name}" / {_make_cstruct(cstruct_fields)}')
+ from_decoded_fn = Function(
+ "from_decoded",
+ [TypedParam("obj", "dict")],
+ Suite(
+ [from_decoded_dict_check, *variant_name_in_obj_checks, invalid_enum_raise]
+ ),
+ _kind_interface_name(name),
+ )
+ from_json_fn = Function(
+ "from_json",
+ [TypedParam("obj", _json_interface_name(name))],
+ Suite(
+ [
+ *obj_kind_checks,
+ Assign("kind", 'obj["kind"]'),
+ Raise('ValueError(f"Unrecognized enum kind: {kind}")'),
+ ]
+ ),
+ _kind_interface_name(name),
+ )
+ formatted_cstructs = ",".join(cstructs)
+ layout_assignment = Assign(
+ "layout",
+ f"EnumForCodegen({formatted_cstructs})",
+ )
+ json_variants = Union(json_variants_members)
+ type_variants = Union(type_variants_members)
+ kind_type_alias = Assign(_kind_interface_name(name), type_variants)
+ json_type_alias = Assign(_json_interface_name(name), json_variants)
+ return Collection(
+ [
+ *imports,
+ *json_interface_value_field_types,
+ *value_type_aliases,
+ *json_interfaces,
+ *classes,
+ kind_type_alias,
+ json_type_alias,
+ from_decoded_fn,
+ from_json_fn,
+ layout_assignment,
+ ]
+ )
diff --git a/basics/anchorpy-main/src/anchorpy/coder/__init__.py b/basics/anchorpy-main/src/anchorpy/coder/__init__.py
new file mode 100644
index 0000000..1bcf95b
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/coder/__init__.py
@@ -0,0 +1 @@
+"""This subpackage defines the Coder class."""
diff --git a/basics/anchorpy-main/src/anchorpy/coder/accounts.py b/basics/anchorpy-main/src/anchorpy/coder/accounts.py
new file mode 100644
index 0000000..af2f999
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/coder/accounts.py
@@ -0,0 +1,73 @@
+"""This module provides `AccountsCoder` and `_account_discriminator`."""
+from hashlib import sha256
+from typing import Any, Tuple
+
+from anchorpy_core.idl import Idl
+from construct import Adapter, Bytes, Container, Sequence, Switch
+
+from anchorpy.coder.idl import _typedef_layout
+from anchorpy.program.common import NamedInstruction as AccountToSerialize
+
+ACCOUNT_DISCRIMINATOR_SIZE = 8 # bytes
+
+
+class AccountsCoder(Adapter):
+ """Encodes and decodes account data."""
+
+ def __init__(self, idl: Idl) -> None:
+ """Init.
+
+ Args:
+ idl: The parsed IDL object.
+ """
+ self._accounts_layout = {
+ acc.name: _typedef_layout(acc, idl.types, acc.name) for acc in idl.accounts
+ }
+ self.acc_name_to_discriminator = {
+ acc.name: _account_discriminator(acc.name) for acc in idl.accounts
+ }
+ self.discriminator_to_acc_name = {
+ disc: acc_name for acc_name, disc in self.acc_name_to_discriminator.items()
+ }
+ discriminator_to_typedef_layout = {
+ disc: self._accounts_layout[acc_name]
+ for acc_name, disc in self.acc_name_to_discriminator.items()
+ }
+ subcon = Sequence(
+ "discriminator" / Bytes(ACCOUNT_DISCRIMINATOR_SIZE),
+ Switch(lambda this: this.discriminator, discriminator_to_typedef_layout),
+ )
+ super().__init__(subcon) # type: ignore
+
+ def decode(self, obj: bytes) -> Container[Any]:
+ """Decode account data.
+
+ Args:
+ obj: Data to decode.
+
+ Returns:
+ Decoded data.
+ """
+ return self.parse(obj).data
+
+ def _decode(self, obj: Tuple[bytes, Any], context, path) -> AccountToSerialize:
+ return AccountToSerialize(
+ data=obj[1],
+ name=self.discriminator_to_acc_name[obj[0]],
+ )
+
+ def _encode(self, obj: AccountToSerialize, context, path) -> Tuple[bytes, Any]:
+ discriminator = self.acc_name_to_discriminator[obj.name]
+ return discriminator, obj.data
+
+
+def _account_discriminator(name: str) -> bytes:
+ """Calculate unique 8 byte discriminator prepended to all anchor accounts.
+
+ Args:
+ name: The account name.
+
+ Returns:
+ The discriminator in bytes.
+ """
+ return sha256(f"account:{name}".encode()).digest()[:ACCOUNT_DISCRIMINATOR_SIZE]
diff --git a/basics/anchorpy-main/src/anchorpy/coder/coder.py b/basics/anchorpy-main/src/anchorpy/coder/coder.py
new file mode 100644
index 0000000..72cfb62
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/coder/coder.py
@@ -0,0 +1,20 @@
+"""Provides the Coder class."""
+from anchorpy_core.idl import Idl
+
+from anchorpy.coder.accounts import AccountsCoder
+from anchorpy.coder.event import EventCoder
+from anchorpy.coder.instruction import InstructionCoder
+
+
+class Coder:
+ """Coder provides a facade for encoding and decoding all IDL related objects."""
+
+ def __init__(self, idl: Idl):
+ """Initialize the coder.
+
+ Args:
+ idl: a parsed Idl instance.
+ """
+ self.instruction: InstructionCoder = InstructionCoder(idl)
+ self.accounts: AccountsCoder = AccountsCoder(idl)
+ self.events: EventCoder = EventCoder(idl)
diff --git a/basics/anchorpy-main/src/anchorpy/coder/common.py b/basics/anchorpy-main/src/anchorpy/coder/common.py
new file mode 100644
index 0000000..8a8872b
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/coder/common.py
@@ -0,0 +1,125 @@
+"""Common utilities for encoding and decoding."""
+from hashlib import sha256
+from typing import Dict, Union
+
+from anchorpy_core.idl import (
+ Idl,
+ IdlEnumVariant,
+ IdlField,
+ IdlType,
+ IdlTypeArray,
+ IdlTypeCompound,
+ IdlTypeDefined,
+ IdlTypeDefinition,
+ IdlTypeDefinitionTyEnum,
+ IdlTypeOption,
+ IdlTypeSimple,
+ IdlTypeVec,
+)
+
+
+def _sighash(ix_name: str) -> bytes:
+ """Not technically sighash, since we don't include the arguments.
+
+ (Because Rust doesn't allow function overloading.)
+
+ Args:
+ ix_name: The instruction name.
+
+ Returns:
+ The sighash bytes.
+ """
+ formatted_str = f"global:{ix_name}"
+ return sha256(formatted_str.encode()).digest()[:8]
+
+
+def _type_size_compound_type(idl: Idl, ty: IdlTypeCompound) -> int:
+ if isinstance(ty, IdlTypeVec):
+ return 1
+ if isinstance(ty, IdlTypeOption):
+ return 1 + _type_size(idl, ty.option)
+ if isinstance(ty, IdlTypeDefined):
+ defined = ty.defined
+ filtered = [t for t in idl.types if t.name == defined]
+ if len(filtered) != 1:
+ raise ValueError(f"Type not found {ty}")
+ type_def = filtered[0]
+ return _account_size(idl, type_def)
+ if isinstance(ty, IdlTypeArray):
+ element_type = ty.array[0]
+ array_size = ty.array[1]
+ return _type_size(idl, element_type) * array_size
+ raise ValueError(f"type_size not implemented for {ty}")
+
+
+def _type_size(idl: Idl, ty: IdlType) -> int:
+ """Return the size of the type in bytes.
+
+ For variable length types, just return 1.
+ Users should override this value in such cases.
+
+ Args:
+ idl: The parsed `Idl` object.
+ ty: The type object from the IDL.
+
+ Returns:
+ The size of the object in bytes.
+ """
+ sizes: Dict[IdlTypeSimple, int] = {
+ IdlTypeSimple.Bool: 1,
+ IdlTypeSimple.U8: 1,
+ IdlTypeSimple.I8: 1,
+ IdlTypeSimple.Bytes: 1,
+ IdlTypeSimple.String: 1,
+ IdlTypeSimple.I16: 2,
+ IdlTypeSimple.U16: 2,
+ IdlTypeSimple.U32: 4,
+ IdlTypeSimple.I32: 4,
+ IdlTypeSimple.F32: 4,
+ IdlTypeSimple.U64: 8,
+ IdlTypeSimple.I64: 8,
+ IdlTypeSimple.F64: 8,
+ IdlTypeSimple.U128: 16,
+ IdlTypeSimple.I128: 16,
+ IdlTypeSimple.PublicKey: 32,
+ }
+ if isinstance(ty, IdlTypeSimple):
+ return sizes[ty]
+ return _type_size_compound_type(idl, ty)
+
+
+def _variant_field_size(idl: Idl, field: Union[IdlField, IdlType]) -> int:
+ if isinstance(field, IdlField):
+ return _type_size(idl, field.ty)
+ return _type_size(idl, field)
+
+
+def _variant_size(idl: Idl, variant: IdlEnumVariant) -> int:
+ if variant.fields is None:
+ return 0
+ field_sizes = []
+ field: Union[IdlField, IdlType]
+ for field in variant.fields.fields:
+ field_sizes.append(_variant_field_size(idl, field))
+ return sum(field_sizes)
+
+
+def _account_size(idl: Idl, idl_account: IdlTypeDefinition) -> int:
+ """Calculate account size in bytes.
+
+ Args:
+ idl: The parsed `Idl` instance.
+ idl_account: An item from `idl.accounts`.
+
+ Returns:
+ Account size.
+ """
+ idl_account_type = idl_account.ty
+ if isinstance(idl_account_type, IdlTypeDefinitionTyEnum):
+ variant_sizes = (
+ _variant_size(idl, variant) for variant in idl_account_type.variants
+ )
+ return max(variant_sizes) + 1
+ if idl_account_type.fields is None:
+ return 0
+ return sum(_type_size(idl, f.ty) for f in idl_account_type.fields)
diff --git a/basics/anchorpy-main/src/anchorpy/coder/event.py b/basics/anchorpy-main/src/anchorpy/coder/event.py
new file mode 100644
index 0000000..5abd0a2
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/coder/event.py
@@ -0,0 +1,82 @@
+"""This module deals with (de)serializing Anchor events."""
+from hashlib import sha256
+from typing import Any, Dict, Optional, Tuple
+
+from anchorpy_core.idl import (
+ Idl,
+ IdlEvent,
+ IdlField,
+ IdlTypeDefinition,
+ IdlTypeDefinitionTyStruct,
+)
+from construct import Adapter, Bytes, Construct, Sequence, Switch
+from pyheck import snake
+
+from anchorpy.coder.idl import _typedef_layout
+from anchorpy.program.common import Event
+
+
+def _event_discriminator(name: str) -> bytes:
+ """Get 8-byte discriminator from event name.
+
+ Args:
+ name: The event name.
+
+ Returns:
+ Discriminator
+ """
+ return sha256(f"event:{name}".encode()).digest()[:8]
+
+
+def _event_layout(event: IdlEvent, idl: Idl) -> Construct:
+ event_type_def = IdlTypeDefinition(
+ name=event.name,
+ docs=None,
+ ty=IdlTypeDefinitionTyStruct(
+ fields=[
+ IdlField(name=snake(f.name), docs=None, ty=f.ty) for f in event.fields
+ ],
+ ),
+ )
+ return _typedef_layout(event_type_def, idl.types, event.name)
+
+
+class EventCoder(Adapter):
+ """Encodes and decodes Anchor events."""
+
+ def __init__(self, idl: Idl):
+ """Initialize the EventCoder.
+
+ Args:
+ idl: The parsed Idl object.
+ """
+ self.idl = idl
+ idl_events = idl.events
+ layouts: Dict[str, Construct]
+ if idl_events:
+ layouts = {event.name: _event_layout(event, idl) for event in idl_events}
+ else:
+ layouts = {}
+ self.layouts = layouts
+ self.discriminators: Dict[bytes, str] = (
+ {}
+ if idl_events is None
+ else {_event_discriminator(event.name): event.name for event in idl_events}
+ )
+ self.discriminator_to_layout = {
+ disc: self.layouts[event_name]
+ for disc, event_name in self.discriminators.items()
+ }
+ subcon = Sequence(
+ "discriminator" / Bytes(8), # not base64-encoded here
+ Switch(lambda this: this.discriminator, self.discriminator_to_layout),
+ )
+ super().__init__(subcon) # type: ignore
+
+ def _decode(self, obj: Tuple[bytes, Any], context, path) -> Optional[Event]:
+ disc = obj[0]
+ try:
+ event_name = self.discriminators[disc]
+ except KeyError:
+ return None
+ return Event(data=obj[1], name=event_name)
diff --git a/basics/anchorpy-main/src/anchorpy/coder/idl.py b/basics/anchorpy-main/src/anchorpy/coder/idl.py
new file mode 100644
index 0000000..5651ae3
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/coder/idl.py
@@ -0,0 +1,325 @@
+"""IDL coding."""
+from dataclasses import fields as dc_fields
+from dataclasses import make_dataclass
+from keyword import kwlist
+from types import MappingProxyType
+from typing import Mapping, Type, cast
+
+from anchorpy_core.idl import (
+ IdlField,
+ IdlType,
+ IdlTypeArray,
+ IdlTypeDefined,
+ IdlTypeDefinition,
+ IdlTypeDefinitionTyEnum,
+ IdlTypeDefinitionTyStruct,
+ IdlTypeOption,
+ IdlTypeSimple,
+ IdlTypeVec,
+)
+from borsh_construct import (
+ F32,
+ F64,
+ I8,
+ I16,
+ I32,
+ I64,
+ I128,
+ U8,
+ U16,
+ U32,
+ U64,
+ U128,
+ Bool,
+ Bytes,
+ CStruct,
+ Enum,
+ Option,
+ String,
+ TupleStruct,
+ Vec,
+)
+from construct import Construct
+from pyheck import snake
+
+from anchorpy.borsh_extension import BorshPubkey, _DataclassStruct
+from anchorpy.idl import TypeDefs
+
+FIELD_TYPE_MAP: Mapping[IdlTypeSimple, Construct] = MappingProxyType(
+ {
+ IdlTypeSimple.Bool: Bool,
+ IdlTypeSimple.U8: U8,
+ IdlTypeSimple.I8: I8,
+ IdlTypeSimple.U16: U16,
+ IdlTypeSimple.I16: I16,
+ IdlTypeSimple.U32: U32,
+ IdlTypeSimple.I32: I32,
+ IdlTypeSimple.F32: F32,
+ IdlTypeSimple.U64: U64,
+ IdlTypeSimple.I64: I64,
+ IdlTypeSimple.F64: F64,
+ IdlTypeSimple.U128: U128,
+ IdlTypeSimple.I128: I128,
+ IdlTypeSimple.Bytes: Bytes,
+ IdlTypeSimple.String: String,
+ IdlTypeSimple.PublicKey: BorshPubkey,
+ },
+)
+
+
+_enums_cache: dict[tuple[str, str], Enum] = {}
+
+
+def _handle_enum_variants(
+ idl_enum: IdlTypeDefinitionTyEnum,
+ types: TypeDefs,
+ name: str,
+) -> Enum:
+ dict_key = (name, str(idl_enum))
+ try:
+ return _enums_cache[dict_key]
+ except KeyError:
+ result = _handle_enum_variants_no_cache(idl_enum, types, name)
+ _enums_cache[dict_key] = result
+ return result
+
+
+def _handle_enum_variants_no_cache(
+ idl_enum: IdlTypeDefinitionTyEnum,
+ types: TypeDefs,
+ name: str,
+) -> Enum:
+ variants = []
+ dclasses = {}
+ for variant in idl_enum.variants:
+ variant_name = variant.name
+ if variant.fields is None:
+ variants.append(variant_name)
+ else:
+ variant_fields = variant.fields
+ flds = variant_fields.fields
+ if isinstance(flds[0], IdlField):
+ fields = []
+ named_fields = cast(list[IdlField], flds)
+ for fld in named_fields:
+ fields.append(_field_layout(fld, types))
+ cstruct = CStruct(*fields)
+ datacls = _idl_enum_fields_named_to_dataclass_type(
+ named_fields,
+ variant_name,
+ )
+ dclasses[variant_name] = datacls
+ renamed = variant_name / cstruct
+ else:
+ fields = []
+ unnamed_fields = cast(list[IdlType], flds)
+ for type_ in unnamed_fields:
+ fields.append(_type_layout(type_, types))
+ tuple_struct = TupleStruct(*fields)
+ renamed = variant_name / tuple_struct
+ variants.append(renamed) # type: ignore
+ enum_without_types = Enum(*variants, enum_name=name)
+ if dclasses:
+ for cname in enum_without_types.enum._sumtype_constructor_names:
+ try:
+ dclass = dclasses[cname]
+ except KeyError:
+ continue
+ dclass_fields = dc_fields(dclass)
+ constructr = getattr(enum_without_types.enum, cname)
+ for constructor_field in constructr._sumtype_attribs:
+ attrib = constructor_field[1] # type: ignore
+ fld_name = constructor_field[0] # type: ignore
+ dclass_field = [f for f in dclass_fields if f.name == fld_name][0]
+ attrib.type = dclass_field.type # type: ignore
+ return enum_without_types
+
+
+def _typedef_layout_without_field_name(
+ typedef: IdlTypeDefinition,
+ types: TypeDefs,
+) -> Construct:
+ typedef_type = typedef.ty
+ name = typedef.name
+ if isinstance(typedef_type, IdlTypeDefinitionTyStruct):
+ field_layouts = [_field_layout(field, types) for field in typedef_type.fields]
+ cstruct = CStruct(*field_layouts)
+ datacls = _idl_typedef_ty_struct_to_dataclass_type(typedef_type, name)
+ return _DataclassStruct(cstruct, datacls=datacls)
+ elif isinstance(typedef_type, IdlTypeDefinitionTyEnum):
+ return _handle_enum_variants(typedef_type, types, name)
+ unknown_type = typedef_type.kind
+ raise ValueError(f"Unknown type {unknown_type}")
+
+
+def _typedef_layout(
+ typedef: IdlTypeDefinition,
+ types: list[IdlTypeDefinition],
+ field_name: str,
+) -> Construct:
+ """Map an IDL typedef to a `Construct` object.
+
+ Args:
+ typedef: The IDL typedef object.
+ types: IDL type definitions.
+ field_name: The name of the field.
+
+ Raises:
+ ValueError: If an unknown type is passed.
+
+ Returns:
+ `Construct` object from `borsh-construct`.
+ """
+ return field_name / _typedef_layout_without_field_name(typedef, types)
+
+
+def _type_layout(type_: IdlType, types: TypeDefs) -> Construct:
+ if isinstance(type_, IdlTypeSimple):
+ return FIELD_TYPE_MAP[type_]
+ if isinstance(type_, IdlTypeVec):
+ return Vec(_type_layout(type_.vec, types))
+ elif isinstance(type_, IdlTypeOption):
+ return Option(_type_layout(type_.option, types))
+ elif isinstance(type_, IdlTypeDefined):
+ defined = type_.defined
+ if not types:
+ raise ValueError("User defined types not provided")
+ filtered = [t for t in types if t.name == defined]
+ if len(filtered) != 1:
+ raise ValueError(f"Type not found {defined}")
+ return _typedef_layout_without_field_name(filtered[0], types)
+ elif isinstance(type_, IdlTypeArray):
+ array_ty = type_.array[0]
+ array_len = type_.array[1]
+ inner_layout = _type_layout(array_ty, types)
+ return inner_layout[array_len]
+ raise ValueError(f"Type {type_} not implemented yet")
+
+
+def _field_layout(field: IdlField, types: TypeDefs) -> Construct:
+ """Map IDL spec to `borsh-construct` types.
+
+ Args:
+ field: field object from the IDL.
+ types: IDL type definitions.
+
+ Raises:
+ ValueError: If the user-defined types are not provided.
+ ValueError: If the type is not found.
+ ValueError: If the type is not implemented yet.
+
+ Returns:
+ `Construct` object from `borsh-construct`.
+ """
+ field_name = snake(field.name) if field.name else ""
+ return field_name / _type_layout(field.ty, types)
+
+
+def _make_datacls(name: str, fields: list[str]) -> type:
+ return make_dataclass(name, fields)
+
+
+_idl_typedef_ty_struct_to_dataclass_type_cache: dict[tuple[str, str], Type] = {}
+
+
+def _idl_typedef_ty_struct_to_dataclass_type(
+ typedef_type: IdlTypeDefinitionTyStruct,
+ name: str,
+) -> Type:
+ dict_key = (name, str(typedef_type))
+ try:
+ return _idl_typedef_ty_struct_to_dataclass_type_cache[dict_key]
+ except KeyError:
+ result = _idl_typedef_ty_struct_to_dataclass_type_no_cache(typedef_type, name)
+ _idl_typedef_ty_struct_to_dataclass_type_cache[dict_key] = result
+ return result
+
+
+def _idl_typedef_ty_struct_to_dataclass_type_no_cache(
+ typedef_type: IdlTypeDefinitionTyStruct,
+ name: str,
+) -> Type:
+ """Generate a dataclass definition from an IDL struct.
+
+ Args:
+ typedef_type: The IDL type.
+ name: The name of the dataclass.
+
+ Returns:
+ Dataclass definition.
+ """
+ dataclass_fields = []
+ for field in typedef_type.fields:
+ field_name = snake(field.name)
+ field_name_to_use = f"{field_name}_" if field_name in kwlist else field_name
+ dataclass_fields.append(
+ field_name_to_use,
+ )
+ return _make_datacls(name, dataclass_fields)
+
+
+_idl_enum_fields_named_to_dataclass_type_cache: dict[tuple[str, str], Type] = {}
+
+
+def _idl_enum_fields_named_to_dataclass_type(
+ fields: list[IdlField],
+ name: str,
+) -> Type:
+ dict_key = (name, str(fields))
+ try:
+ return _idl_enum_fields_named_to_dataclass_type_cache[dict_key]
+ except KeyError:
+ result = _idl_enum_fields_named_to_dataclass_type_no_cache(fields, name)
+ _idl_enum_fields_named_to_dataclass_type_cache[dict_key] = result
+ return result
+
+
+def _idl_enum_fields_named_to_dataclass_type_no_cache(
+ fields: list[IdlField],
+ name: str,
+) -> Type:
+ """Generate a dataclass definition from IDL named enum fields.
+
+ Args:
+ fields: The IDL enum fields.
+ name: The name of the dataclass.
+
+ Returns:
+ Dataclass type definition.
+ """
+ dataclass_fields = []
+ for field in fields:
+ field_name = snake(field.name)
+ field_name_to_use = f"{field_name}_" if field_name in kwlist else field_name
+ dataclass_fields.append(
+ field_name_to_use,
+ )
+ return _make_datacls(name, dataclass_fields)
+
+
+def _idl_typedef_to_python_type(
+ typedef: IdlTypeDefinition,
+ types: TypeDefs,
+) -> Type:
+ """Generate Python type from IDL user-defined type.
+
+ Args:
+ typedef: The user-defined type.
+ types: IDL type definitions.
+
+ Raises:
+ ValueError: If an unknown type is passed.
+
+ Returns:
+ The Python type.
+ """
+ typedef_type = typedef.ty
+ if isinstance(typedef_type, IdlTypeDefinitionTyStruct):
+ return _idl_typedef_ty_struct_to_dataclass_type(
+ typedef_type,
+ typedef.name,
+ )
+ elif isinstance(typedef_type, IdlTypeDefinitionTyEnum):
+ return _handle_enum_variants(typedef_type, types, typedef.name).enum
+ unknown_type = typedef_type.kind
+ raise ValueError(f"Unknown type {unknown_type}")
diff --git a/basics/anchorpy-main/src/anchorpy/coder/instruction.py b/basics/anchorpy-main/src/anchorpy/coder/instruction.py
new file mode 100644
index 0000000..e648f44
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/coder/instruction.py
@@ -0,0 +1,98 @@
+"""This module deals (de)serializing program instructions."""
+from typing import Any, Dict, Protocol, Tuple, TypeVar, cast
+
+from anchorpy_core.idl import Idl
+from borsh_construct import CStruct
+from construct import Adapter, Bytes, Construct, Container, Sequence, Switch
+from pyheck import snake
+
+from anchorpy.coder.common import _sighash
+from anchorpy.coder.idl import _field_layout
+from anchorpy.idl import TypeDefs
+from anchorpy.program.common import NamedInstruction
+
+
+class _Sighash(Adapter):
+ """Sighash as a Construct Adapter."""
+
+ def __init__(self) -> None:
+ """Initialize."""
+ super().__init__(Bytes(8)) # type: ignore
+
+ def _encode(self, obj: str, context, path) -> bytes:
+ return _sighash(obj)
+
+ def _decode(self, obj: bytes, context, path):
+ raise ValueError("Sighash cannot be reversed")
+
+
+class InstructionCoder(Adapter):
+ """Encodes and decodes program instructions."""
+
+ def __init__(self, idl: Idl) -> None:
+ """Init.
+
+ Args:
+ idl: The parsed IDL object.
+ """
+ self.ix_layout = _parse_ix_layout(idl)
+ sighasher = _Sighash()
+ sighash_layouts: Dict[bytes, Construct] = {}
+ sighashes: Dict[str, bytes] = {}
+ sighash_to_name: Dict[bytes, str] = {}
+ for ix in idl.instructions:
+ ix_name = snake(ix.name)
+ sh = sighasher.build(ix_name)
+ sighashes[ix_name] = sh
+ sighash_layouts[sh] = self.ix_layout[ix_name]
+ sighash_to_name[sh] = ix_name
+ self.sighash_layouts = sighash_layouts
+ self.sighashes = sighashes
+ self.sighash_to_name = sighash_to_name
+ subcon = Sequence(
+ "sighash" / Bytes(8),
+ Switch(lambda this: this.sighash, sighash_layouts),
+ )
+ super().__init__(subcon) # type: ignore
+
+ def encode(self, ix_name: str, ix: Dict[str, Any]) -> bytes:
+ """Encode a program instruction.
+
+ Args:
+ ix_name: The name of the instruction
+ ix: The data to encode.
+
+ Returns:
+ The encoded instruction.
+ """
+ return self.build(NamedInstruction(name=ix_name, data=ix))
+
+ def _decode(self, obj: Tuple[bytes, Any], context, path) -> NamedInstruction:
+ return NamedInstruction(data=obj[1], name=self.sighash_to_name[obj[0]])
+
+ def _encode(
+ self, obj: NamedInstruction, context: Container, path
+ ) -> Tuple[bytes, Any]:
+ return (self.sighashes[obj.name], obj.data)
+
+
+_SA = TypeVar("_SA", bound="_SupportsAdd")
+
+
+class _SupportsAdd(Protocol):
+ """Any type T where +(:T, :T) -> T."""
+
+ def __add__(self: _SA, other: _SA) -> _SA:
+ ...
+
+
+def _parse_ix_layout(idl: Idl) -> Dict[str, Construct]:
+ ix_layout: Dict[str, Construct] = {}
+ for ix in idl.instructions:
+ typedefs = cast(_SupportsAdd, idl.accounts) + cast(_SupportsAdd, idl.types)
+ field_layouts = [
+ _field_layout(arg, cast(TypeDefs, typedefs)) for arg in ix.args
+ ]
+ ix_name = snake(ix.name)
+ ix_layout[ix_name] = ix_name / CStruct(*field_layouts)
+ return ix_layout
diff --git a/basics/anchorpy-main/src/anchorpy/error.py b/basics/anchorpy-main/src/anchorpy/error.py
new file mode 100644
index 0000000..ef7aa6b
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/error.py
@@ -0,0 +1,340 @@
+"""This module handles AnchorPy errors."""
+from __future__ import annotations
+
+import re
+from enum import IntEnum
+from typing import Dict, List, Optional, Tuple
+
+from solders.pubkey import Pubkey
+from solders.rpc.errors import SendTransactionPreflightFailureMessage
+from solders.rpc.responses import RPCError
+from solders.transaction_status import (
+ InstructionErrorCustom,
+ TransactionErrorInstructionError,
+ TransactionErrorType,
+)
+
+
+class AccountDoesNotExistError(Exception):
+ """Raise if account doesn't exist."""
+
+
+class AccountInvalidDiscriminator(Exception):
+ """Raise if account discriminator doesn't match the IDL."""
+
+
+class IdlNotFoundError(Exception):
+ """Raise when requested IDL account does not exist."""
+
+
+class ArgsError(Exception):
+ """Raise when the incorrect number of args is passed to the RPC function."""
+
+
+class _LangErrorCode(IntEnum):
+ """Enumerates Anchor error codes."""
+
+ # Instructions.
+ InstructionMissing = 100
+ InstructionFallbackNotFound = 101
+ InstructionDidNotDeserialize = 102
+ InstructionDidNotSerialize = 103
+ # IDL instructions.
+ IdlInstructionStub = 1000
+ IdlInstructionInvalidProgram = 1001
+ # Constraints.
+ ConstraintMut = 2000
+ ConstraintHasOne = 2001
+ ConstraintSigner = 2002
+ ConstraintRaw = 2003
+ ConstraintOwner = 2004
+ ConstraintRentExempt = 2005
+ ConstraintSeeds = 2006
+ ConstraintExecutable = 2007
+ ConstraintState = 2008
+ ConstraintAssociated = 2009
+ ConstraintAssociatedInit = 2010
+ ConstraintClose = 2011
+ ConstraintAddress = 2012
+ ConstraintZero = 2013
+ ConstraintTokenMint = 2014
+ ConstraintTokenOwner = 2015
+ ConstraintMintMintAuthority = 2016
+ ConstraintMintFreezeAuthority = 2017
+ ConstraintMintDecimals = 2018
+ ConstraintSpace = 2019
+ # Require
+ RequireViolated = 2500
+ RequireEqViolated = 2501
+ RequireKeysEqViolated = 2502
+ RequireNeqViolated = 2503
+ RequireKeysNeqViolated = 2504
+ RequireGtViolated = 2505
+ RequireGteViolated = 2506
+ # Accounts.
+ AccountDiscriminatorAlreadySet = 3000
+ AccountDiscriminatorNotFound = 3001
+ AccountDiscriminatorMismatch = 3002
+ AccountDidNotDeserialize = 3003
+ AccountDidNotSerialize = 3004
+ AccountNotEnoughKeys = 3005
+ AccountNotMutable = 3006
+ AccountOwnedByWrongProgram = 3007
+ InvalidProgramId = 3008
+ InvalidProgramExecutable = 3009
+ AccountNotSigner = 3010
+ AccountNotSystemOwned = 3011
+ AccountNotInitialized = 3012
+ AccountNotProgramData = 3013
+ AccountNotAssociatedTokenAccount = 3014
+ AccountSysvarMismatch = 3015
+ # State.
+ StateInvalidAddress = 4000
+
+ # Used for APIs that shouldn't be used anymore.
+ Deprecated = 5000
+
+
+LangErrorMessage: Dict[int, str] = {
+ # Instructions.
+ _LangErrorCode.InstructionMissing: "8 byte instruction identifier not provided",
+ _LangErrorCode.InstructionFallbackNotFound: "Fallback functions are not supported",
+ _LangErrorCode.InstructionDidNotDeserialize: (
+ "The program could not deserialize the given instruction"
+ ),
+ _LangErrorCode.InstructionDidNotSerialize: (
+ "The program could not serialize the given instruction"
+ ),
+ # Idl instructions.
+ _LangErrorCode.IdlInstructionStub: (
+ "The program was compiled without idl instructions"
+ ),
+ _LangErrorCode.IdlInstructionInvalidProgram: (
+ "The transaction was given an invalid program for the IDL instruction"
+ ),
+ # Constraints.
+ _LangErrorCode.ConstraintMut: "A mut constraint was violated",
+ _LangErrorCode.ConstraintHasOne: "A has_one constraint was violated",
+ _LangErrorCode.ConstraintSigner: "A signer constraint was violated",
+ _LangErrorCode.ConstraintRaw: "A raw constraint was violated",
+ _LangErrorCode.ConstraintOwner: "An owner constraint was violated",
+ _LangErrorCode.ConstraintRentExempt: "A rent exempt constraint was violated",
+ _LangErrorCode.ConstraintSeeds: "A seeds constraint was violated",
+ _LangErrorCode.ConstraintExecutable: "An executable constraint was violated",
+ _LangErrorCode.ConstraintState: "A state constraint was violated",
+ _LangErrorCode.ConstraintAssociated: "An associated constraint was violated",
+ _LangErrorCode.ConstraintAssociatedInit: (
+ "An associated init constraint was violated"
+ ),
+ _LangErrorCode.ConstraintClose: "A close constraint was violated",
+ _LangErrorCode.ConstraintAddress: "An address constraint was violated",
+ _LangErrorCode.ConstraintZero: "Expected zero account discriminant",
+ _LangErrorCode.ConstraintTokenMint: "A token mint constraint was violated",
+ _LangErrorCode.ConstraintTokenOwner: "A token owner constraint was violated",
+ _LangErrorCode.ConstraintMintMintAuthority: (
+ "A mint mint authority constraint was violated"
+ ),
+ _LangErrorCode.ConstraintMintFreezeAuthority: (
+ "A mint freeze authority constraint was violated"
+ ),
+ _LangErrorCode.ConstraintMintDecimals: "A mint decimals constraint was violated",
+ _LangErrorCode.ConstraintSpace: "A space constraint was violated",
+ # Require.
+ _LangErrorCode.RequireViolated: "A require expression was violated",
+ _LangErrorCode.RequireEqViolated: "A require_eq expression was violated",
+ _LangErrorCode.RequireKeysEqViolated: "A require_keys_eq expression was violated",
+ _LangErrorCode.RequireNeqViolated: "A require_neq expression was violated",
+ _LangErrorCode.RequireKeysNeqViolated: "A require_keys_neq expression was violated",
+ _LangErrorCode.RequireGtViolated: "A require_gt expression was violated",
+ _LangErrorCode.RequireGteViolated: "A require_gte expression was violated",
+ # Accounts.
+ _LangErrorCode.AccountDiscriminatorAlreadySet: (
+ "The account discriminator was already set on this account"
+ ),
+ _LangErrorCode.AccountDiscriminatorNotFound: (
+ "No 8 byte discriminator was found on the account"
+ ),
+ _LangErrorCode.AccountDiscriminatorMismatch: (
+ "8 byte discriminator did not match what was expected"
+ ),
+ _LangErrorCode.AccountDidNotDeserialize: "Failed to deserialize the account",
+ _LangErrorCode.AccountDidNotSerialize: "Failed to serialize the account",
+ _LangErrorCode.AccountNotEnoughKeys: (
+ "Not enough account keys given to the instruction"
+ ),
+ _LangErrorCode.AccountNotMutable: "The given account is not mutable",
+ _LangErrorCode.AccountOwnedByWrongProgram: (
+ "The given account is owned by a different program than expected"
+ ),
+ _LangErrorCode.InvalidProgramId: "Program ID was not as expected",
+ _LangErrorCode.InvalidProgramExecutable: "Program account is not executable",
+ _LangErrorCode.AccountNotSigner: "The given account did not sign",
+ _LangErrorCode.AccountNotSystemOwned: (
+ "The given account is not owned by the system program"
+ ),
+ _LangErrorCode.AccountNotInitialized: (
+ "The program expected this account to be already initialized"
+ ),
+ _LangErrorCode.AccountNotProgramData: (
+ "The given account is not a program data account"
+ ),
+ _LangErrorCode.AccountNotAssociatedTokenAccount: (
+ "The given account is not the associated token account"
+ ),
+ _LangErrorCode.AccountSysvarMismatch: (
+ "The given public key does not match the required sysvar"
+ ),
+ # State.
+ _LangErrorCode.StateInvalidAddress: (
+ "The given state account does not have the correct address"
+ ),
+ # Misc.
+ _LangErrorCode.Deprecated: (
+ "The API being used is deprecated and should no longer be used"
+ ),
+}
+
+
+class ProgramError(Exception):
+ """An error from a user defined program."""
+
+ def __init__(
+ self, code: int, msg: Optional[str], logs: Optional[list[str]] = None
+ ) -> None:
+ """Init.
+
+ Args:
+ code: The error code.
+ msg: The error message.
+ logs: The transaction simulation logs.
+ """
+ self.code = code
+ self.msg = msg
+ self.logs = logs
+ super().__init__(f"{code}: {msg}")
+
+ @classmethod
+ def parse(
+ cls,
+ err_info: RPCError,
+ idl_errors: dict[int, str],
+ program_id: Pubkey,
+ ) -> Optional[ProgramError]:
+ """Convert an RPC error into a ProgramError, if possible.
+
+ Args:
+ err_info: The RPC error.
+ idl_errors: Errors from the IDL file.
+ program_id: The ID of the program we expect the error to come from.
+
+ Returns:
+ A ProgramError or None.
+ """
+ extracted = extract_code_and_logs(err_info, program_id)
+ if extracted is None:
+ return None
+ code, logs = extracted
+ msg = idl_errors.get(code)
+ if msg is not None:
+ return cls(code, msg, logs)
+ # parse framework internal error
+ msg = LangErrorMessage.get(code)
+ if msg is not None:
+ return cls(code, msg, logs)
+ # Unable to parse the error.
+ return None
+
+ @classmethod
+ def parse_tx_error(
+ cls,
+ err_info: TransactionErrorType,
+ idl_errors: dict[int, str],
+ program_id: Pubkey,
+ logs: List[str],
+ ) -> Optional[ProgramError]:
+ """Convert an RPC error into a ProgramError, if possible.
+
+ Args:
+ err_info: The RPC error.
+ idl_errors: Errors from the IDL file.
+ program_id: The ID of the program we expect the error to come from.
+ logs: The transaction logs.
+
+ Returns:
+ A ProgramError or None.
+ """
+ code = extract_code_tx_error(err_info, program_id, logs)
+ if code is None:
+ return None
+ msg = idl_errors.get(code)
+ if msg is not None:
+ return cls(code, msg, logs)
+ # parse framework internal error
+ msg = LangErrorMessage.get(code)
+ if msg is not None:
+ return cls(code, msg, logs)
+ # Unable to parse the error.
+ return None
+
+
+error_re = re.compile(r"Program (\w+) failed: custom program error: (\w+)")
+
+
+def _find_first_match(logs: list[str]) -> Optional[re.Match]:
+ for logline in logs:
+ first_match = error_re.match(logline)
+ if first_match is not None:
+ return first_match
+ return None
+
+
+def extract_code_and_logs(
+ err_info: RPCError, program_id: Pubkey
+) -> Optional[Tuple[int, List[str]]]:
+ """Extract the custom instruction error code from an RPC response.
+
+ Args:
+ err_info: The RPC error.
+ program_id: The ID of the program we expect the error to come from.
+ """
+ if isinstance(err_info, SendTransactionPreflightFailureMessage):
+ err_data = err_info.data
+ err_data_err = err_data.err
+ logs = err_data.logs
+ if logs is None:
+ return None
+ if err_data_err is None:
+ return None
+ maybe_code = _handle_ix_err(err_data_err, logs, program_id)
+ return None if maybe_code is None else (maybe_code, logs)
+ return None
+
+
+def extract_code_tx_error(
+ err_info: TransactionErrorType, program_id: Pubkey, logs: List[str]
+) -> Optional[int]:
+ """Extract the custom instruction error code from a transaction error.
+
+ Args:
+ err_info: The tx error.
+ program_id: The ID of the program we expect the error to come from.
+ logs: The tx logs.
+ """
+ return _handle_ix_err(err_info, logs, program_id)
+
+
+def _handle_ix_err(
+ err: TransactionErrorType, logs: List[str], program_id: Pubkey
+) -> Optional[int]:
+ if isinstance(err, TransactionErrorInstructionError):
+ instruction_err = err.err
+ if isinstance(instruction_err, InstructionErrorCustom):
+ code = instruction_err.code
+ first_match = _find_first_match(logs)
+ if first_match is None:
+ return None
+ program_id_raw, _ = first_match.groups()
+ if program_id_raw != str(program_id):
+ return None
+ return code
+ return None
diff --git a/basics/anchorpy-main/src/anchorpy/idl.py b/basics/anchorpy-main/src/anchorpy/idl.py
new file mode 100644
index 0000000..a4a27ee
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/idl.py
@@ -0,0 +1,46 @@
+"""Contains code for parsing the IDL file."""
+from typing import Sequence, TypedDict
+
+import solders.pubkey
+from anchorpy_core.idl import IdlTypeDefinition
+from borsh_construct import U8, CStruct, Vec
+
+from anchorpy.borsh_extension import BorshPubkey
+
+
+def _idl_address(program_id: solders.pubkey.Pubkey) -> solders.pubkey.Pubkey:
+ """Deterministic IDL address as a function of the program id.
+
+ Args:
+ program_id: The program ID.
+
+ Returns:
+ The public key of the IDL.
+ """
+ base = solders.pubkey.Pubkey.find_program_address([], program_id)[0]
+ return solders.pubkey.Pubkey.create_with_seed(base, "anchor:idl", program_id)
+
+
+class IdlProgramAccount(TypedDict):
+ """The on-chain account of the IDL."""
+
+ authority: solders.pubkey.Pubkey
+ data: bytes
+
+
+IDL_ACCOUNT_LAYOUT = CStruct("authority" / BorshPubkey, "data" / Vec(U8))
+
+
+def _decode_idl_account(data: bytes) -> IdlProgramAccount:
+ """Decode on-chain IDL.
+
+ Args:
+ data: binary data from the account that stores the IDL.
+
+ Returns:
+ Decoded IDL.
+ """
+ return IDL_ACCOUNT_LAYOUT.parse(data)
+
+
+TypeDefs = Sequence[IdlTypeDefinition]
diff --git a/basics/anchorpy-main/src/anchorpy/program/__init__.py b/basics/anchorpy-main/src/anchorpy/program/__init__.py
new file mode 100644
index 0000000..46bbdd9
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/__init__.py
@@ -0,0 +1 @@
+"""This subpacakge defines the `Program` class."""
diff --git a/basics/anchorpy-main/src/anchorpy/program/common.py b/basics/anchorpy-main/src/anchorpy/program/common.py
new file mode 100644
index 0000000..8dd0979
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/common.py
@@ -0,0 +1,90 @@
+"""Common utilities."""
+from dataclasses import dataclass
+from typing import Any, Dict, NamedTuple, Tuple, Union, cast
+
+from anchorpy_core.idl import (
+ IdlAccountItem,
+ IdlAccounts,
+ IdlInstruction,
+)
+from construct import Container
+from pyheck import snake
+from solders.pubkey import Pubkey
+
+from anchorpy.program.context import Accounts
+
+AddressType = Union[Pubkey, str]
+
+
+class Event(NamedTuple):
+ """A parsed event object."""
+
+ name: str
+ data: Any
+
+
+@dataclass
+class NamedInstruction:
+ """Container for a named instruction.
+
+ Attributes:
+ data: The actual instruction data.
+ name: The name of the instruction.
+ """
+
+ data: Union[Dict[str, Any], Container[Any]]
+ name: str
+
+
+def _to_instruction(idl_ix: IdlInstruction, args: Tuple) -> NamedInstruction:
+ """Convert an IDL instruction and arguments to an Instruction object.
+
+ Args:
+ idl_ix: The IDL instruction object.
+ args: The instruction arguments.
+
+ Raises:
+ ValueError: If the incorrect number of arguments is provided.
+
+ Returns:
+ The parsed Instruction object.
+ """
+ if len(idl_ix.args) != len(args):
+ raise ValueError("Invalid argument length")
+ ix: Dict[str, Any] = {}
+ for idx, ix_arg in enumerate(idl_ix.args):
+ ix[snake(ix_arg.name)] = args[idx]
+ return NamedInstruction(data=ix, name=snake(idl_ix.name))
+
+
+def validate_accounts(ix_accounts: list[IdlAccountItem], accounts: Accounts):
+ """Check that accounts passed in `ctx` match the IDL.
+
+ Args:
+ ix_accounts: Accounts from the IDL.
+ accounts: Accounts from the `ctx` arg.
+
+ Raises:
+ ValueError: If `ctx` accounts don't match the IDL.
+ """
+ for acc in ix_accounts:
+ acc_name = snake(acc.name)
+ if isinstance(acc, IdlAccounts):
+ nested = cast(Accounts, accounts[acc_name])
+ validate_accounts(acc.accounts, nested)
+ elif acc_name not in accounts:
+ raise ValueError(f"Invalid arguments: {acc_name} not provided")
+
+
+def translate_address(address: AddressType) -> Pubkey:
+ """Convert `str | Pubkey` into `Pubkey`.
+
+ Args:
+ address: Public key as string or `Pubkey`.
+
+ Returns:
+ Public key as `Pubkey`.
+ """
+ if isinstance(address, str):
+ return Pubkey.from_string(address)
+ return address
diff --git a/basics/anchorpy-main/src/anchorpy/program/context.py b/basics/anchorpy-main/src/anchorpy/program/context.py
new file mode 100644
index 0000000..8da74e4
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/context.py
@@ -0,0 +1,69 @@
+"""This module contains code handling the Context object."""
+from dataclasses import dataclass, field
+from typing import Any, Dict, List, Optional, Tuple
+
+from anchorpy_core.idl import IdlInstruction
+from pyheck import snake
+from solana.rpc.types import TxOpts
+from solders.instruction import AccountMeta, Instruction
+from solders.keypair import Keypair
+
+from anchorpy.error import ArgsError
+
+# should be Dict[str, Union[Pubkey, Accounts]]
+# but mypy doesn't support recursive types
+Accounts = Dict[str, Any]
+
+
+@dataclass
+class Context:
+ """Context provides all non-argument inputs for generating Anchor transactions.
+
+ Attributes:
+ accounts: The accounts used in the instruction context.
+ remaining_accounts: All accounts to pass into an instruction *after* the main
+ `accounts`. This can be used for optional or otherwise unknown accounts.
+ signers: Accounts that must sign a given transaction.
+ pre_instructions: Instructions to run *before* a given method. Often this is
+ used, for example to create accounts prior to executing a method.
+ post_instructions: Instructions to run *after* a given method. Often this is
+ used, for example to close accounts prior to executing a method.
+ options: Commitment parameters to use for a transaction.
+
+ """
+
+ # For some reason mkdocstrings doesn't understand the full type hint
+ # here if we use list[Instruction] instead of typing.List.
+ # Weirdly there are other places where it understands list[whatever].
+
+ accounts: Accounts = field(default_factory=dict)
+ remaining_accounts: List[AccountMeta] = field(default_factory=list)
+ signers: List[Keypair] = field(default_factory=list)
+ pre_instructions: List[Instruction] = field(default_factory=list)
+ post_instructions: List[Instruction] = field(default_factory=list)
+ options: Optional[TxOpts] = None
+
+
+def _check_args_length(
+ idl_ix: IdlInstruction,
+ args: Tuple,
+) -> None:
+ """Check that the correct number of args is passed to the RPC function.
+
+ Args:
+ idl_ix: The IDL instruction object.
+ args: The instruction arguments.
+
+ Raises:
+ ArgsError: If the correct number of args is not parsed.
+ """
+ if len(args) != len(idl_ix.args):
+ expected_arg_names = [snake(arg.name) for arg in idl_ix.args]
+ raise ArgsError(
+ f"Provided incorrect number of args to instruction={snake(idl_ix.name)}. "
+ f"Expected {expected_arg_names}",
+ f"Received {args}",
+ )
+
+
+EMPTY_CONTEXT = Context()
diff --git a/basics/anchorpy-main/src/anchorpy/program/core.py b/basics/anchorpy-main/src/anchorpy/program/core.py
new file mode 100644
index 0000000..65e69a4
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/core.py
@@ -0,0 +1,264 @@
+"""This module defines the Program class."""
+from __future__ import annotations
+
+import zlib
+from typing import Any, Optional
+
+from anchorpy_core.idl import Idl
+from pyheck import snake
+from solders.pubkey import Pubkey
+
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.coder.coder import Coder
+from anchorpy.error import IdlNotFoundError
+from anchorpy.idl import _decode_idl_account, _idl_address
+from anchorpy.program.common import AddressType, translate_address
+from anchorpy.program.namespace.account import AccountClient, _build_account
+from anchorpy.program.namespace.instruction import (
+ _InstructionFn,
+)
+from anchorpy.program.namespace.methods import (
+ IdlFuncs,
+ MethodsBuilder,
+ _build_methods_item,
+)
+from anchorpy.program.namespace.rpc import (
+ _build_rpc_item,
+ _RpcFn,
+)
+from anchorpy.program.namespace.simulate import (
+ _build_simulate_item,
+ _SimulateFn,
+)
+from anchorpy.program.namespace.transaction import (
+ _build_transaction_fn,
+ _TransactionFn,
+)
+from anchorpy.program.namespace.types import _build_types
+from anchorpy.provider import Provider
+
+
+def _parse_idl_errors(idl: Idl) -> dict[int, str]:
+ """Turn IDL errors into something readable.
+
+ Uses message if available, otherwise name.
+
+ Args:
+ idl: Parsed `Idl` instance.
+
+ """
+ errors = {}
+ idl_errors = idl.errors
+ if idl_errors is not None:
+ for e in idl_errors:
+ msg = e.msg if e.msg else e.name
+ errors[e.code] = msg
+ return errors
+
+
+def _build_namespace(
+ idl: Idl,
+ coder: Coder,
+ program_id: Pubkey,
+ provider: Provider,
+) -> tuple[
+ dict[str, _RpcFn],
+ dict[str, _InstructionFn],
+ dict[str, _TransactionFn],
+ dict[str, AccountClient],
+ dict[str, _SimulateFn],
+ dict[str, Any],
+ dict[str, MethodsBuilder],
+]:
+ """Generate all namespaces for a given program.
+
+ Args:
+ idl: The parsed IDL object.
+ coder: The program's Coder object .
+ program_id: The Program ID.
+ provider: The program's provider.
+
+ Returns:
+ The program namespaces.
+ """
+ idl_errors = _parse_idl_errors(idl)
+
+ rpc = {}
+ instruction = {}
+ transaction = {}
+ simulate = {}
+ methods = {}
+
+ for idl_ix in idl.instructions:
+
+ ix_item = _InstructionFn(idl_ix, coder.instruction.build, program_id)
+ tx_item = _build_transaction_fn(idl_ix, ix_item)
+ rpc_item = _build_rpc_item(idl_ix, tx_item, idl_errors, provider, program_id)
+ simulate_item = _build_simulate_item(
+ idl_ix,
+ tx_item,
+ idl_errors,
+ provider,
+ coder,
+ program_id,
+ idl,
+ )
+ idl_funcs = IdlFuncs(
+ ix_fn=ix_item, tx_fn=tx_item, rpc_fn=rpc_item, simulate_fn=simulate_item
+ )
+ methods_item = _build_methods_item(idl_funcs)
+
+ name = snake(idl_ix.name)
+ instruction[name] = ix_item
+ transaction[name] = tx_item
+ rpc[name] = rpc_item
+ simulate[name] = simulate_item
+ methods[name] = methods_item
+
+ account = _build_account(idl, coder, program_id, provider) if idl.accounts else {}
+ types = _build_types(idl)
+ return rpc, instruction, transaction, account, simulate, types, methods
+
+
+def _pako_inflate(data):
+ # https://stackoverflow.com/questions/46351275/using-pako-deflate-with-python
+ decompress = zlib.decompressobj(15)
+ decompressed_data = decompress.decompress(data)
+ decompressed_data += decompress.flush()
+ return decompressed_data
+
+
+class Program(object):
+ """Program provides the IDL deserialized client representation of an Anchor program.
+
+ This API is the one stop shop for all things related to communicating with
+ on-chain programs. Among other things, one can send transactions, fetch
+ deserialized accounts, decode instruction data, subscribe to account
+ changes, and listen to events.
+
+ In addition to field accessors and methods, the object provides a set of
+ dynamically generated properties, also known as namespaces, that
+ map one-to-one to program methods and accounts.
+
+ """
+
+ def __init__(
+ self, idl: Idl, program_id: Pubkey, provider: Optional[Provider] = None
+ ):
+ """Initialize the Program object.
+
+ Args:
+ idl: The parsed IDL object.
+ program_id: The program ID.
+ provider: The Provider object for the Program. Defaults to Provider.local().
+ """
+ self.idl = idl
+ self.program_id = program_id
+ self.provider = provider if provider is not None else Provider.local()
+ self.coder = Coder(idl)
+
+ (
+ rpc,
+ instruction,
+ transaction,
+ account,
+ simulate,
+ types,
+ methods,
+ ) = _build_namespace(
+ idl,
+ self.coder,
+ program_id,
+ self.provider,
+ )
+
+ self.rpc = rpc
+ self.instruction = instruction
+ self.transaction = transaction
+ self.account = account
+ self.simulate = simulate
+ self.type = types
+ self.methods = methods
+
+ async def __aenter__(self) -> Program:
+ """Use as a context manager."""
+ await self.provider.__aenter__()
+ return self
+
+ async def __aexit__(self, _exc_type, _exc, _tb):
+ """Exit the context manager."""
+ await self.close()
+
+ async def close(self) -> None:
+ """Use this when you are done with the client."""
+ await self.provider.close()
+
+ @staticmethod
+ async def fetch_raw_idl(
+ address: AddressType,
+ provider: Provider,
+ ) -> str:
+ """Fetch an idl from the blockchain as a raw JSON dictionary.
+
+ Args:
+ address: The program ID.
+ provider: The network and wallet context.
+
+ Raises:
+ IdlNotFoundError: If the requested IDL account does not exist.
+
+ Returns:
+ str: The raw IDL.
+ """
+ program_id = translate_address(address)
+ actual_provider = provider if provider is not None else Provider.local()
+ idl_addr = _idl_address(program_id)
+ account_info = await actual_provider.connection.get_account_info(idl_addr)
+ account_info_val = account_info.value
+ if account_info_val is None:
+ raise IdlNotFoundError(f"IDL not found for program: {address}")
+ idl_account = _decode_idl_account(
+ account_info_val.data[ACCOUNT_DISCRIMINATOR_SIZE:]
+ )
+ return _pako_inflate(bytes(idl_account["data"])).decode()
+
+ @classmethod
+ async def fetch_idl(
+ cls,
+ address: AddressType,
+ provider: Provider,
+ ) -> Idl:
+ """Fetch and parse an idl from the blockchain.
+
+ Args:
+ address: The program ID.
+ provider: The network and wallet context.
+
+ Returns:
+ Idl: The fetched IDL.
+ """
+ raw = await cls.fetch_raw_idl(address, provider)
+ return Idl.from_json(raw)
+
+ @classmethod
+ async def at(
+ cls,
+ address: AddressType,
+ provider: Optional[Provider] = None,
+ ) -> Program:
+ """Generate a Program client by fetching the IDL from the network.
+
+ In order to use this method, an IDL must have been previously initialized
+ via the anchor CLI's `anchor idl init` command.
+
+ Args:
+ address: The program ID.
+ provider: The network and wallet context.
+
+ Returns:
+ The Program instantiated using the fetched IDL.
+ """
+ provider_to_use = Provider.local() if provider is None else provider
+ program_id = translate_address(address)
+ idl = await cls.fetch_idl(program_id, provider_to_use)
+ return cls(idl, program_id, provider)
diff --git a/basics/anchorpy-main/src/anchorpy/program/event.py b/basics/anchorpy-main/src/anchorpy/program/event.py
new file mode 100644
index 0000000..dbccfe1
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/event.py
@@ -0,0 +1,166 @@
+"""This module contains code for handling Anchor events."""
+import binascii
+from base64 import b64decode
+from dataclasses import dataclass
+from typing import Callable, List, Optional, cast
+
+from solders.pubkey import Pubkey
+
+from anchorpy.coder.coder import Coder
+from anchorpy.program.common import Event
+
+PROGRAM_LOG = "Program log: "
+PROGRAM_DATA = "Program data: "
+PROGRAM_LOG_START_INDEX = len(PROGRAM_LOG)
+PROGRAM_DATA_START_INDEX = len(PROGRAM_DATA)
+
+
+class _ExecutionContext:
+ """Stack frame execution context, allowing one to track what program is executing for a given log.""" # noqa: E501
+
+ def __init__(self, log: str) -> None:
+ """Init.
+
+ Args:
+ log: The log to process.
+
+ Raises:
+ ValueError: If the log line is malformed.
+ """
+ try:
+ program = log.split("Program ")[1].split(" invoke [")[0]
+ except IndexError as e:
+ raise ValueError("Could not find program invocation log line") from e
+ self.stack = [program]
+
+ def program(self) -> str:
+ """Return the currently executing program.
+
+ Returns:
+ The name of the program.
+ """
+ return self.stack[-1]
+
+ def push(self, new_program: str) -> None:
+ """Add to the stack.
+
+ Args:
+ new_program: The program to add.
+ """
+ self.stack.append(new_program)
+
+ def pop(self) -> None:
+ """Pop from the stack."""
+ self.stack.pop()
+
+
+@dataclass
+class EventParser:
+ """Parser to handle on_logs callbacks."""
+
+ program_id: Pubkey
+ coder: Coder
+
+ def parse_logs(self, logs: List[str], callback: Callable[[Event], None]) -> None:
+ """Parse a list of logs using a provided callback.
+
+ Args:
+ logs: The logs to parse.
+ callback: The function to handle the parsed log.
+ """
+ log_scanner = _LogScanner(logs)
+ execution = _ExecutionContext(cast(str, log_scanner.to_next()))
+ log = log_scanner.to_next()
+ while log is not None:
+ event, new_program, did_pop = self.handle_log(execution, log)
+ if event is not None:
+ callback(event)
+ if new_program is not None:
+ execution.push(new_program)
+ if did_pop:
+ execution.pop()
+ log = log_scanner.to_next()
+
+ def handle_log(
+ self,
+ execution: _ExecutionContext,
+ log: str,
+ ) -> tuple[Optional[Event], Optional[str], bool]:
+ """Main log handler.
+
+ Args:
+ execution: The execution stack.
+ log: log string from the RPC node.
+
+ Returns:
+ A three element array of the event, the next program
+ that was invoked for CPI, and a boolean indicating if
+ a program has completed execution (and thus should be popped off the
+ execution stack).
+ """
+ # Executing program is this program.
+ if execution.stack and execution.program() == str(self.program_id):
+ return self.handle_program_log(log)
+ # Executing program is not this program.
+ return (None, *self.handle_system_log(log))
+
+ def handle_program_log(
+ self, log: str
+ ) -> tuple[Optional[Event], Optional[str], bool]:
+ """Handle logs from *this* program.
+
+ Args:
+ log: log string from the RPC node.
+
+ """
+ # This is a `msg!` log or a `sol_log_data!` log.
+ if log.startswith(PROGRAM_LOG) or log.startswith(PROGRAM_DATA):
+ log_str = (
+ log[PROGRAM_LOG_START_INDEX:]
+ if log.startswith(PROGRAM_LOG)
+ else log[PROGRAM_DATA_START_INDEX:]
+ )
+ try:
+ decoded = b64decode(log_str)
+ except binascii.Error:
+ return None, None, False
+ event = self.coder.events.parse(decoded)
+ return event, None, False
+ return (None, *self.handle_system_log(log))
+
+ def handle_system_log(self, log: str) -> tuple[Optional[str], bool]:
+ """Handle logs when the current program being executing is *not* this.
+
+ Args:
+ log: log string from the RPC node.
+
+ """
+ log_start = log.split(":")[0]
+ splitted = log_start.split(" ")
+ invoke_msg = f"Program {str(self.program_id)} invoke"
+ if len(splitted) == 3 and splitted[0] == "Program" and splitted[2] == "success":
+ return None, True
+ if log_start.startswith(invoke_msg):
+ return str(self.program_id), False
+ if "invoke" in log_start:
+ return "cpi", False
+ return None, False
+
+
+@dataclass
+class _LogScanner:
+ """Object that iterates over logs."""
+
+ logs: list[str]
+
+ def to_next(self) -> Optional[str]:
+ """Move to the next log item.
+
+ Returns:
+ The next log line, or None if there's nothing to return.
+ """
+ if self.logs:
+ log = self.logs[0]
+ self.logs = self.logs[1:]
+ return log
+ return None
diff --git a/basics/anchorpy-main/src/anchorpy/program/namespace/__init__.py b/basics/anchorpy-main/src/anchorpy/program/namespace/__init__.py
new file mode 100644
index 0000000..cc1abae
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/namespace/__init__.py
@@ -0,0 +1 @@
+"""This subpackage deals with the dynamic namespaces under `Program`."""
diff --git a/basics/anchorpy-main/src/anchorpy/program/namespace/account.py b/basics/anchorpy-main/src/anchorpy/program/namespace/account.py
new file mode 100644
index 0000000..133e5fd
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/namespace/account.py
@@ -0,0 +1,231 @@
+"""Provides the `AccountClient` class."""
+from dataclasses import dataclass
+from typing import Any, Dict, List, Optional, Sequence, Union
+
+from anchorpy_core.idl import Idl, IdlTypeDefinition
+from based58 import b58encode
+from construct import Container
+from solana.rpc.commitment import Commitment
+from solana.rpc.types import MemcmpOpts
+from solana.transaction import Instruction
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.system_program import CreateAccountParams, create_account
+
+from anchorpy.coder.accounts import (
+ ACCOUNT_DISCRIMINATOR_SIZE,
+ _account_discriminator,
+)
+from anchorpy.coder.coder import Coder
+from anchorpy.coder.common import _account_size
+from anchorpy.error import AccountDoesNotExistError, AccountInvalidDiscriminator
+from anchorpy.provider import Provider
+from anchorpy.utils.rpc import get_multiple_accounts
+
+
+def _build_account(
+ idl: Idl,
+ coder: Coder,
+ program_id: Pubkey,
+ provider: Provider,
+) -> Dict[str, "AccountClient"]:
+ """Generate the `.account` namespace.
+
+ Args:
+ idl: The parsed Idl object.
+ coder: The program's coder object.
+ program_id: The program ID.
+ provider: The Provider instance.
+
+ Returns:
+ Mapping of account name to `AccountClient` instance.
+ """
+ accounts_fns = {}
+ for idl_account in idl.accounts:
+ account_client = AccountClient(idl, idl_account, coder, program_id, provider)
+ accounts_fns[idl_account.name] = account_client
+ return accounts_fns
+
+
+@dataclass
+class ProgramAccount:
+ """Deserialized account owned by a program."""
+
+ public_key: Pubkey
+ account: Container
+
+
+class AccountClient(object):
+ """Provides methods for fetching and creating accounts."""
+
+ def __init__(
+ self,
+ idl: Idl,
+ idl_account: IdlTypeDefinition,
+ coder: Coder,
+ program_id: Pubkey,
+ provider: Provider,
+ ):
+ """Init.
+
+ Args:
+ idl: the parsed IDL object.
+ idl_account: the account definition from the IDL.
+ coder: The program's Coder object.
+ program_id: the program ID.
+ provider: The Provider object for the Program.
+ """
+ self._idl_account = idl_account
+ self._program_id = program_id
+ self._provider = provider
+ self._coder = coder
+ self._size = ACCOUNT_DISCRIMINATOR_SIZE + _account_size(idl, idl_account)
+
+ async def fetch(
+ self, address: Pubkey, commitment: Optional[Commitment] = None
+ ) -> Container[Any]:
+ """Return a deserialized account.
+
+ Args:
+ address: The address of the account to fetch.
+ commitment: Bank state to query.
+
+
+ Raises:
+ AccountDoesNotExistError: If the account doesn't exist.
+ AccountInvalidDiscriminator: If the discriminator doesn't match the IDL.
+ """
+ account_info = await self._provider.connection.get_account_info(
+ address,
+ encoding="base64",
+ commitment=commitment,
+ )
+ if not account_info.value:
+ raise AccountDoesNotExistError(f"Account {address} does not exist")
+ data = account_info.value.data
+ discriminator = _account_discriminator(self._idl_account.name)
+ if discriminator != data[:ACCOUNT_DISCRIMINATOR_SIZE]:
+ msg = f"Account {address} has an invalid discriminator"
+ raise AccountInvalidDiscriminator(msg)
+ return self._coder.accounts.decode(data)
+
+ async def fetch_multiple(
+ self,
+ addresses: List[Pubkey],
+ batch_size: int = 300,
+ commitment: Optional[Commitment] = None,
+ ) -> list[Optional[Container[Any]]]:
+ """Return multiple deserialized accounts.
+
+ Accounts not found or with wrong discriminator are returned as None.
+
+ Args:
+ addresses: The addresses of the accounts to fetch.
+ batch_size: The number of `getMultipleAccounts` objects to send
+ in each HTTP request.
+ commitment: Bank state to query.
+ """
+ accounts = await get_multiple_accounts(
+ self._provider.connection,
+ addresses,
+ batch_size=batch_size,
+ commitment=commitment,
+ )
+ discriminator = _account_discriminator(self._idl_account.name)
+ result: list[Optional[Container[Any]]] = []
+ for account in accounts:
+ if account is None:
+ result.append(None)
+ elif discriminator == account.account.data[:8]:
+ result.append(self._coder.accounts.decode(account.account.data))
+ else:
+ result.append(None)
+ return result
+
+ async def create_instruction(
+ self,
+ signer: Keypair,
+ size_override: int = 0,
+ ) -> Instruction:
+ """Return an instruction for creating this account.
+
+ Args:
+ signer: [description]
+ size_override: Optional override for the account size. Defaults to 0.
+
+ Returns:
+ The instruction to create the account.
+ """
+ space = size_override if size_override else self._size
+ mbre_resp = (
+ await self._provider.connection.get_minimum_balance_for_rent_exemption(
+ space
+ )
+ )
+ return create_account(
+ CreateAccountParams(
+ from_pubkey=self._provider.wallet.public_key,
+ to_pubkey=signer.pubkey(),
+ space=space,
+ lamports=mbre_resp.value,
+ owner=self._program_id,
+ )
+ )
+
+ async def all( # noqa: A003
+ self,
+ buffer: Optional[bytes] = None,
+ filters: Optional[Sequence[Union[int, MemcmpOpts]]] = None,
+ ) -> list[ProgramAccount]:
+ """Return all instances of this account type for the program.
+
+ Args:
+ buffer: bytes filter to append to the discriminator.
+ filters: (optional) Options to compare a provided series of bytes with
+ program account data at a particular offset.
+ Note: an int entry is converted to a `dataSize` filter.
+ """
+ all_accounts = []
+ discriminator = _account_discriminator(self._idl_account.name)
+ to_encode = discriminator if buffer is None else discriminator + buffer
+ bytes_arg = b58encode(to_encode).decode("ascii")
+ base_memcmp_opt = MemcmpOpts(
+ offset=0,
+ bytes=bytes_arg,
+ )
+ filters_to_use = [base_memcmp_opt] + [] if filters is None else filters
+ resp = await self._provider.connection.get_program_accounts(
+ self._program_id,
+ encoding="base64",
+ commitment=self.provider.connection._commitment,
+ filters=filters_to_use,
+ )
+ for r in resp.value:
+ account_data = r.account.data
+ all_accounts.append(
+ ProgramAccount(
+ public_key=r.pubkey,
+ account=self._coder.accounts.decode(account_data),
+ ),
+ )
+ return all_accounts
+
+ @property
+ def size(self) -> int:
+ """Return the number of bytes in this account."""
+ return self._size
+
+ @property
+ def program_id(self) -> Pubkey:
+ """Return the program ID owning all accounts."""
+ return self._program_id
+
+ @property
+ def provider(self) -> Provider:
+ """Return the client's wallet and network provider."""
+ return self._provider
+
+ @property
+ def coder(self) -> Coder:
+ """Return the coder."""
+ return self._coder
diff --git a/basics/anchorpy-main/src/anchorpy/program/namespace/instruction.py b/basics/anchorpy-main/src/anchorpy/program/namespace/instruction.py
new file mode 100644
index 0000000..64b5176
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/namespace/instruction.py
@@ -0,0 +1,127 @@
+"""This module deals with generating program instructions."""
+from typing import Any, Callable, Sequence, Tuple, cast
+
+from anchorpy_core.idl import IdlAccount, IdlAccountItem, IdlAccounts, IdlInstruction
+from pyheck import snake
+from solders.instruction import AccountMeta, Instruction
+from solders.pubkey import Pubkey
+
+from anchorpy.program.common import (
+ NamedInstruction,
+ _to_instruction,
+ validate_accounts,
+)
+from anchorpy.program.context import (
+ EMPTY_CONTEXT,
+ Accounts,
+ Context,
+ _check_args_length,
+)
+
+
+class _InstructionFn:
+ """Callable object to create a `Instruction` generated from an IDL.
+
+ Additionally it provides an `accounts` utility method, returning a list
+ of ordered accounts for the instruction.
+ """
+
+ def __init__(
+ self,
+ idl_ix: IdlInstruction,
+ encode_fn: Callable[[NamedInstruction], bytes],
+ program_id: Pubkey,
+ ) -> None:
+ """Init.
+
+ Args:
+ idl_ix: IDL instruction object
+ encode_fn: [description]
+ program_id: The program ID.
+
+ Raises:
+ ValueError: [description]
+ """
+ if snake(idl_ix.name) == "_inner":
+ raise ValueError("_inner name is reserved")
+ self.idl_ix = idl_ix
+ self.encode_fn = encode_fn
+ self.program_id = program_id
+
+ def __call__(
+ self,
+ *args: Any,
+ ctx: Context = EMPTY_CONTEXT,
+ ) -> Instruction:
+ """Create the Instruction.
+
+ Args:
+ *args: The positional arguments for the program. The type and number
+ of these arguments depend on the program being used.
+ ctx: non-argument parameters to pass to the method.
+ """
+ _check_args_length(self.idl_ix, args)
+ validate_accounts(self.idl_ix.accounts, ctx.accounts)
+ _validate_instruction(self.idl_ix, args)
+
+ keys = self.accounts(ctx.accounts)
+ if ctx.remaining_accounts:
+ keys.extend(ctx.remaining_accounts)
+ return Instruction(
+ accounts=keys,
+ program_id=self.program_id,
+ data=self.encode_fn(_to_instruction(self.idl_ix, args)),
+ )
+
+ def accounts(self, accs: Accounts) -> list[AccountMeta]:
+ """Order the accounts for this instruction.
+
+ Args:
+ accs: Accounts from `ctx` kwarg.
+
+ Returns:
+ Ordered and flattened accounts.
+ """
+ return _accounts_array(accs, self.idl_ix.accounts)
+
+
+def _accounts_array(
+ ctx: Accounts,
+ accounts: Sequence[IdlAccountItem],
+) -> list[AccountMeta]:
+ """Create a list of AccountMeta from a (possibly nested) dict of accounts.
+
+ Args:
+ ctx: `accounts` field from the `Context` object.
+ accounts: accounts from the IDL.
+
+ Returns:
+ AccountMeta objects.
+ """
+ accounts_ret: list[AccountMeta] = []
+ for acc in accounts:
+ if isinstance(acc, IdlAccounts):
+ rpc_accs = cast(Accounts, ctx[snake(acc.name)])
+ acc_arr = _accounts_array(rpc_accs, acc.accounts)
+ accounts_ret.extend(acc_arr)
+ else:
+ account: IdlAccount = acc
+ single_account = cast(Pubkey, ctx[snake(account.name)])
+ accounts_ret.append(
+ AccountMeta(
+ pubkey=single_account,
+ is_writable=account.is_mut,
+ is_signer=account.is_signer,
+ ),
+ )
+ return accounts_ret
+
+
+def _validate_instruction(ix: IdlInstruction, args: Tuple): # noqa: ARG001
+ """Throws error if any argument required for the `ix` is not given.
+
+ Args:
+ ix: The IDL instruction object.
+ args: The instruction arguments.
+ """
+ # TODO: this isn't implemented in the TS client yet
diff --git a/basics/anchorpy-main/src/anchorpy/program/namespace/methods.py b/basics/anchorpy-main/src/anchorpy/program/namespace/methods.py
new file mode 100644
index 0000000..bec2a76
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/namespace/methods.py
@@ -0,0 +1,158 @@
+from dataclasses import dataclass
+from typing import Any, List, Optional
+
+from solana.rpc import types
+from solders.hash import Hash
+from solders.instruction import AccountMeta, Instruction
+from solders.keypair import Keypair
+from solders.signature import Signature
+from solders.transaction import VersionedTransaction
+
+from anchorpy.program.context import Accounts, Context
+from anchorpy.program.namespace.instruction import _InstructionFn
+from anchorpy.program.namespace.rpc import _RpcFn
+from anchorpy.program.namespace.simulate import SimulateResponse, _SimulateFn
+from anchorpy.program.namespace.transaction import _TransactionFn
+
+
+@dataclass
+class IdlFuncs:
+ ix_fn: _InstructionFn
+ tx_fn: _TransactionFn
+ rpc_fn: _RpcFn
+ simulate_fn: _SimulateFn
+
+
+class MethodsBuilder:
+ def __init__(
+ self,
+ idl_funcs: IdlFuncs,
+ accounts: Accounts,
+ remaining_accounts: List[AccountMeta],
+ signers: List[Keypair],
+ pre_instructions: List[Instruction],
+ post_instructions: List[Instruction],
+ args: List[Any],
+ ) -> None:
+ self._idl_funcs = idl_funcs
+ self._accounts = accounts
+ self._remaining_accounts = remaining_accounts
+ self._signers = signers
+ self._pre_instructions = pre_instructions
+ self._post_instructions = post_instructions
+ self._args = args
+
+ async def rpc(self, opts: Optional[types.TxOpts] = None) -> Signature:
+ ctx = self._build_context(opts)
+ return await self._idl_funcs.rpc_fn(*self._args, ctx=ctx)
+
+ async def simulate(self, opts: Optional[types.TxOpts] = None) -> SimulateResponse:
+ ctx = self._build_context(opts)
+ return await self._idl_funcs.simulate_fn(*self._args, ctx=ctx)
+
+ def instruction(self) -> Instruction:
+ ctx = self._build_context(opts=None)
+ return self._idl_funcs.ix_fn(*self._args, ctx=ctx)
+
+ def transaction(self, payer: Keypair, blockhash: Hash) -> VersionedTransaction:
+ ctx = self._build_context(opts=None)
+ return self._idl_funcs.tx_fn(
+ *self._args, ctx=ctx, payer=payer, blockhash=blockhash
+ )
+
+ def pubkeys(self) -> Accounts:
+ return self._accounts
+
+ def args(self, arguments: List[Any]) -> "MethodsBuilder":
+ idl_funcs = self._idl_funcs
+ return MethodsBuilder(
+ idl_funcs=idl_funcs,
+ accounts=self._accounts,
+ remaining_accounts=self._remaining_accounts,
+ signers=self._signers,
+ pre_instructions=self._pre_instructions,
+ post_instructions=self._post_instructions,
+ args=arguments,
+ )
+
+ def accounts(self, accs: Accounts) -> "MethodsBuilder":
+ idl_funcs = self._idl_funcs
+ return MethodsBuilder(
+ idl_funcs=idl_funcs,
+ accounts=accs,
+ remaining_accounts=self._remaining_accounts,
+ signers=self._signers,
+ pre_instructions=self._pre_instructions,
+ post_instructions=self._post_instructions,
+ args=self._args,
+ )
+
+ def signers(self, signers: List[Keypair]) -> "MethodsBuilder":
+ idl_funcs = self._idl_funcs
+ return MethodsBuilder(
+ idl_funcs=idl_funcs,
+ accounts=self._accounts,
+ remaining_accounts=self._remaining_accounts,
+ signers=self._signers + signers,
+ pre_instructions=self._pre_instructions,
+ post_instructions=self._post_instructions,
+ args=self._args,
+ )
+
+ def remaining_accounts(self, accounts: List[AccountMeta]) -> "MethodsBuilder":
+ idl_funcs = self._idl_funcs
+ return MethodsBuilder(
+ idl_funcs=idl_funcs,
+ accounts=self._accounts,
+ remaining_accounts=self._remaining_accounts + accounts,
+ signers=self._signers,
+ pre_instructions=self._pre_instructions,
+ post_instructions=self._post_instructions,
+ args=self._args,
+ )
+
+ def pre_instructions(self, ixs: List[Instruction]) -> "MethodsBuilder":
+ idl_funcs = self._idl_funcs
+ return MethodsBuilder(
+ idl_funcs=idl_funcs,
+ accounts=self._accounts,
+ remaining_accounts=self._remaining_accounts,
+ signers=self._signers,
+ pre_instructions=self._pre_instructions + ixs,
+ post_instructions=self._post_instructions,
+ args=self._args,
+ )
+
+ def post_instructions(self, ixs: List[Instruction]) -> "MethodsBuilder":
+ idl_funcs = self._idl_funcs
+ return MethodsBuilder(
+ idl_funcs=idl_funcs,
+ accounts=self._accounts,
+ remaining_accounts=self._remaining_accounts,
+ signers=self._signers,
+ pre_instructions=self._pre_instructions,
+ post_instructions=self._post_instructions + ixs,
+ args=self._args,
+ )
+
+ def _build_context(self, opts: Optional[types.TxOpts]) -> Context:
+ return Context(
+ accounts=self._accounts,
+ remaining_accounts=self._remaining_accounts,
+ signers=self._signers,
+ pre_instructions=self._pre_instructions,
+ post_instructions=self._post_instructions,
+ options=opts,
+ )
+
+
+def _build_methods_item(idl_funcs: IdlFuncs) -> MethodsBuilder:
+ return MethodsBuilder(
+ idl_funcs=idl_funcs,
+ accounts={},
+ remaining_accounts=[],
+ signers=[],
+ pre_instructions=[],
+ post_instructions=[],
+ args=[],
+ )
diff --git a/basics/anchorpy-main/src/anchorpy/program/namespace/rpc.py b/basics/anchorpy-main/src/anchorpy/program/namespace/rpc.py
new file mode 100644
index 0000000..97da05f
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/namespace/rpc.py
@@ -0,0 +1,71 @@
+"""This module contains code for generating RPC functions."""
+from typing import Any, Awaitable, Dict, Protocol
+
+from anchorpy_core.idl import IdlInstruction
+from solana.rpc.commitment import Confirmed
+from solana.rpc.core import RPCException
+from solders.pubkey import Pubkey
+from solders.signature import Signature
+
+from anchorpy.error import ProgramError
+from anchorpy.program.context import EMPTY_CONTEXT, Context, _check_args_length
+from anchorpy.program.namespace.transaction import _TransactionFn
+from anchorpy.provider import Provider
+
+
+class _RpcFn(Protocol):
+ """_RpcFn is a single RPC method generated from an IDL, sending a transaction paid for and signed by the configured provider.""" # noqa: E501
+
+ def __call__(
+ self,
+ *args: Any,
+ ctx: Context = EMPTY_CONTEXT,
+ ) -> Awaitable[Signature]:
+ """Call the function (this is just a protocol declaration).
+
+ Args:
+ *args: The positional arguments for the program. The type and number
+ of these arguments depend on the program being used.
+ ctx: non-argument parameters to pass to the method.
+ """
+ ...
+
+
+def _build_rpc_item( # ts: RpcFactory
+ idl_ix: IdlInstruction,
+ tx_fn: _TransactionFn,
+ idl_errors: Dict[int, str],
+ provider: Provider,
+ program_id: Pubkey,
+) -> _RpcFn:
+ """Build the function that sends transactions for the given method.
+
+ Args:
+ idl_ix: The IDL instruction object.
+ tx_fn: The function that generates the `Transaction` to send.
+ idl_errors: Mapping of error code to error message.
+ provider: Anchor Provider instance.
+ program_id: The ID of the Anchor program.
+
+ Returns:
+ The RPC function.
+ """
+
+ async def rpc_fn(*args: Any, ctx: Context = EMPTY_CONTEXT) -> Signature:
+ recent_blockhash = (
+ await provider.connection.get_latest_blockhash(Confirmed)
+ ).value.blockhash
+ tx = tx_fn(
+ *args, payer=provider.wallet.payer, blockhash=recent_blockhash, ctx=ctx
+ )
+ _check_args_length(idl_ix, args)
+ try:
+ return await provider.send(tx, ctx.options)
+ except RPCException as e:
+ err_info = e.args[0]
+ translated_err = ProgramError.parse(err_info, idl_errors, program_id)
+ if translated_err is not None:
+ raise translated_err from e
+ raise
+
+ return rpc_fn
diff --git a/basics/anchorpy-main/src/anchorpy/program/namespace/simulate.py b/basics/anchorpy-main/src/anchorpy/program/namespace/simulate.py
new file mode 100644
index 0000000..d354cfc
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/namespace/simulate.py
@@ -0,0 +1,94 @@
+"""This module contains code for creating simulate functions."""
+from typing import Any, Awaitable, Dict, NamedTuple, Protocol
+
+from anchorpy_core.idl import Idl, IdlInstruction
+from solana.rpc.commitment import Confirmed
+from solana.rpc.core import RPCException
+from solders.pubkey import Pubkey
+
+from anchorpy.coder.coder import Coder
+from anchorpy.error import ProgramError
+from anchorpy.program.context import EMPTY_CONTEXT, Context, _check_args_length
+from anchorpy.program.event import Event, EventParser
+from anchorpy.program.namespace.transaction import _TransactionFn
+from anchorpy.provider import Provider
+
+
+class SimulateResponse(NamedTuple):
+ """The result of a simulate function call."""
+
+ events: list[Event]
+ raw: list[str]
+
+
+class _SimulateFn(Protocol):
+ """A single method generated from an IDL.
+
+ It simulates a method against a cluster configured by the provider,
+ returning a list of all the events and raw logs that were emitted
+ during the execution of the method.
+ """
+
+ def __call__(
+ self,
+ *args: Any,
+ ctx: Context = EMPTY_CONTEXT,
+ ) -> Awaitable[SimulateResponse]:
+ """Protocol definition.
+
+ Args:
+ *args: The positional arguments for the program. The type and number
+ of these arguments depend on the program being used.
+ ctx: non-argument parameters to pass to the method.
+
+ """
+
+
+def _build_simulate_item(
+ idl_ix: IdlInstruction,
+ tx_fn: _TransactionFn,
+ idl_errors: Dict[int, str],
+ provider: Provider,
+ coder: Coder,
+ program_id: Pubkey,
+ idl: Idl,
+) -> _SimulateFn:
+ """Build the function to simulate transactions for a given method of a program.
+
+ Args:
+ idl_ix: An IDL instruction object.
+ tx_fn: The function to generate the `Transaction` object.
+ idl_errors: Mapping of error code to message.
+ provider: A provider instance.
+ coder: The program's coder object.
+ program_id: The program ID.
+ idl: The parsed Idl instance.
+
+ Returns:
+ The simulate function.
+ """
+
+ async def simulate_fn(*args: Any, ctx: Context = EMPTY_CONTEXT) -> SimulateResponse:
+ blockhash = (
+ await provider.connection.get_latest_blockhash(Confirmed)
+ ).value.blockhash
+ tx = tx_fn(*args, payer=provider.wallet.payer, blockhash=blockhash, ctx=ctx)
+ _check_args_length(idl_ix, args)
+ resp = (await provider.simulate(tx, ctx.options)).value
+ resp_err = resp.err
+ logs = resp.logs or []
+ if resp_err is None:
+ events = []
+ if idl.events is not None:
+ parser = EventParser(program_id, coder)
+ parser.parse_logs(logs, lambda evt: events.append(evt))
+ return SimulateResponse(events, logs)
+ else:
+ translated_err = ProgramError.parse_tx_error(
+ resp_err, idl_errors, program_id, logs
+ )
+ if translated_err is not None:
+ raise translated_err
+ raise RPCException(resp_err)
+
+ return simulate_fn
diff --git a/basics/anchorpy-main/src/anchorpy/program/namespace/transaction.py b/basics/anchorpy-main/src/anchorpy/program/namespace/transaction.py
new file mode 100644
index 0000000..635d114
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/namespace/transaction.py
@@ -0,0 +1,65 @@
+"""This module deals with generating transactions."""
+from typing import Any, Protocol
+
+from anchorpy_core.idl import IdlInstruction
+from more_itertools import unique_everseen
+from solders.hash import Hash
+from solders.instruction import Instruction
+from solders.keypair import Keypair
+from solders.message import Message
+from solders.transaction import VersionedTransaction
+
+from anchorpy.program.context import EMPTY_CONTEXT, Context, _check_args_length
+from anchorpy.program.namespace.instruction import _InstructionFn
+
+
+class _TransactionFn(Protocol):
+ """A function to create a `Transaction` for a given program instruction."""
+
+ def __call__(
+ self, *args: Any, payer: Keypair, blockhash: Hash, ctx: Context = EMPTY_CONTEXT
+ ) -> VersionedTransaction:
+ """Make sure that the function looks like this.
+
+ Args:
+ *args: The positional arguments for the program. The type and number
+ of these arguments depend on the program being used.
+ payer: The transaction fee payer.
+ blockhash: A recent blockhash.
+ ctx: non-argument parameters to pass to the method.
+
+ """
+ ...
+
+
+# ts TransactionNamespaceFactory.build
+def _build_transaction_fn(
+ idl_ix: IdlInstruction, ix_fn: _InstructionFn
+) -> _TransactionFn:
+ """Build the function that generates Transaction objects.
+
+ Args:
+ idl_ix: Instruction item from the IDL.
+ ix_fn (_InstructionFn): The function that generates instructions.
+
+ Returns:
+ _TransactionFn: [description]
+ """
+
+ def tx_fn(
+ *args: Any, payer: Keypair, blockhash: Hash, ctx: Context = EMPTY_CONTEXT
+ ) -> VersionedTransaction:
+ ixns: list[Instruction] = []
+ _check_args_length(idl_ix, args)
+ if ctx.pre_instructions:
+ ixns.extend(ctx.pre_instructions)
+ ixns.append(ix_fn(*args, ctx=ctx))
+ if ctx.post_instructions:
+ ixns.extend(ctx.post_instructions)
+ ctx_signers = ctx.signers
+ signers = [] if ctx_signers is None else ctx_signers
+ all_signers = list(unique_everseen([payer, *signers]))
+ msg = Message.new_with_blockhash(ixns, payer.pubkey(), blockhash)
+ return VersionedTransaction(msg, all_signers)
+
+ return tx_fn
diff --git a/basics/anchorpy-main/src/anchorpy/program/namespace/types.py b/basics/anchorpy-main/src/anchorpy/program/namespace/types.py
new file mode 100644
index 0000000..47b6711
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/program/namespace/types.py
@@ -0,0 +1,27 @@
+"""This module contains code for handling user-defined types."""
+from typing import Any, Type
+
+from anchorpy_core.idl import Idl
+
+from anchorpy.coder.idl import _idl_typedef_to_python_type
+
+
+def _build_types(
+ idl: Idl,
+) -> dict[str, Type[Any]]:
+ """Generate the `.type` namespace.
+
+ Args:
+ idl: A parsed `Idl` instance.
+
+ Returns:
+ Mapping of type name to Python object.
+ """
+ result = {}
+ for idl_type in idl.types:
+ try:
+ python_type = _idl_typedef_to_python_type(idl_type, idl.types)
+ except ValueError:
+ continue
+ result[idl_type.name] = python_type
+ return result
diff --git a/basics/anchorpy-main/src/anchorpy/provider.py b/basics/anchorpy-main/src/anchorpy/provider.py
new file mode 100644
index 0000000..507ccdb
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/provider.py
@@ -0,0 +1,219 @@
+"""This module contains the Provider class and associated utilities."""
+from __future__ import annotations
+
+import json
+from os import environ, getenv
+from pathlib import Path
+from types import MappingProxyType
+from typing import List, Optional, Sequence, Union
+
+from solana.rpc import types
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Confirmed, Finalized, Processed
+from solana.transaction import Transaction
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.rpc.responses import SimulateTransactionResp
+from solders.signature import Signature
+from solders.transaction import VersionedTransaction
+
+DEFAULT_OPTIONS = types.TxOpts(skip_confirmation=False, preflight_commitment=Processed)
+COMMITMENT_RANKS = MappingProxyType({Processed: 0, Confirmed: 1, Finalized: 2})
+
+
+class Provider:
+ """The network and wallet context used to send transactions paid for and signed by the provider.""" # noqa: E501
+
+ def __init__(
+ self,
+ connection: AsyncClient,
+ wallet: Wallet,
+ opts: types.TxOpts = DEFAULT_OPTIONS,
+ ) -> None:
+ """Initialize the Provider.
+
+ Args:
+ connection: The cluster connection where the program is deployed.
+ wallet: The wallet used to pay for and sign all transactions.
+ opts: Transaction confirmation options to use by default.
+ """
+ self.connection = connection
+ self.wallet = wallet
+ self.opts = opts
+
+ @classmethod
+ def local(
+ cls, url: Optional[str] = None, opts: types.TxOpts = DEFAULT_OPTIONS
+ ) -> Provider:
+ """Create a `Provider` with a wallet read from the local filesystem.
+
+ Args:
+ url: The network cluster url.
+ opts: The default transaction confirmation options.
+ """
+ connection = AsyncClient(url, opts.preflight_commitment)
+ wallet = Wallet.local()
+ return cls(connection, wallet, opts)
+
+ @classmethod
+ def readonly(
+ cls, url: Optional[str] = None, opts: types.TxOpts = DEFAULT_OPTIONS
+ ) -> Provider:
+ """Create a `Provider` that can only fetch data, not send transactions.
+
+ Args:
+ url: The network cluster url.
+ opts: The default transaction confirmation options.
+ """
+ connection = AsyncClient(url, opts.preflight_commitment)
+ wallet = Wallet.dummy()
+ return cls(connection, wallet, opts)
+
+ @classmethod
+ def env(cls) -> Provider:
+ """Create a `Provider` using the `ANCHOR_PROVIDER_URL` environment variable."""
+ url = environ["ANCHOR_PROVIDER_URL"]
+ options = DEFAULT_OPTIONS
+ connection = AsyncClient(url, options.preflight_commitment)
+ wallet = Wallet.local()
+ return cls(connection, wallet, options)
+
+ async def simulate(
+ self,
+ tx: Union[Transaction, VersionedTransaction],
+ opts: Optional[types.TxOpts] = None,
+ ) -> SimulateTransactionResp:
+ """Simulate the given transaction, returning emitted logs from execution.
+
+ Args:
+ tx: The transaction to send.
+ signers: The set of signers in addition to the provider wallet that will
+ sign the transaction.
+ opts: Transaction confirmation options.
+
+ Returns:
+ The transaction simulation result.
+ """
+ if opts is None:
+ opts = self.opts
+ return await self.connection.simulate_transaction(
+ tx, sig_verify=True, commitment=opts.preflight_commitment
+ )
+
+ async def send(
+ self,
+ tx: Union[Transaction, VersionedTransaction],
+ opts: Optional[types.TxOpts] = None,
+ ) -> Signature:
+ """Send the given transaction, paid for and signed by the provider's wallet.
+
+ Args:
+ tx: The transaction to send.
+ signers: The set of signers in addition to the provider wallet that will
+ sign the transaction.
+ opts: Transaction confirmation options.
+
+ Returns:
+ The transaction signature from the RPC server.
+ """
+ if opts is None:
+ opts = self.opts
+ raw = tx.serialize() if isinstance(tx, Transaction) else bytes(tx)
+ resp = await self.connection.send_raw_transaction(raw, opts=opts)
+ return resp.value
+
+ async def send_all(
+ self,
+ txs: Sequence[Union[Transaction, VersionedTransaction]],
+ opts: Optional[types.TxOpts] = None,
+ ) -> list[Signature]:
+ """Similar to `send`, but for an array of transactions and signers.
+
+ Args:
+ txs: a list of transaction objects.
+ opts: Transaction confirmation options.
+
+ Returns:
+ The transaction signatures from the RPC server.
+ """
+ if opts is None:
+ opts = self.opts
+ sigs = []
+ for tx in txs:
+ raw = tx.serialize() if isinstance(tx, Transaction) else bytes(tx)
+ resp = await self.connection.send_raw_transaction(raw, opts=opts)
+ sigs.append(resp.value)
+ return sigs
+
+ async def __aenter__(self) -> Provider:
+ """Use as a context manager."""
+ await self.connection.__aenter__()
+ return self
+
+ async def __aexit__(self, _exc_type, _exc, _tb):
+ """Exit the context manager."""
+ await self.close()
+
+ async def close(self) -> None:
+ """Use this when you are done with the connection."""
+ await self.connection.close()
+
+
+class Wallet:
+ """Python wallet object."""
+
+ def __init__(self, payer: Keypair):
+ """Initialize the wallet.
+
+ Args:
+ payer: the Keypair used to sign transactions.
+ """
+ self.payer = payer
+
+ @property
+ def public_key(self) -> Pubkey:
+ """Get the public key of the wallet."""
+ return self.payer.pubkey()
+
+ def sign_transaction(self, tx: Transaction) -> Transaction:
+ """Sign a transaction using the wallet's keypair.
+
+ Args:
+ tx: The transaction to sign.
+
+ Returns:
+ The signed transaction.
+ """
+ tx.sign(self.payer)
+ return tx
+
+ def sign_all_transactions(self, txs: list[Transaction]) -> list[Transaction]:
+ """Sign a list of transactions using the wallet's keypair.
+
+ Args:
+ txs: The transactions to sign.
+
+ Returns:
+ The signed transactions.
+ """
+ for tx in txs:
+ tx.sign_partial(self.payer)
+ return txs
+
+ @classmethod
+ def local(cls) -> Wallet:
+ """Create a wallet instance from the filesystem.
+
+ Uses the path at the ANCHOR_WALLET env var if set,
+ otherwise uses ~/.config/solana/id.json.
+ """
+ path = Path(getenv("ANCHOR_WALLET", Path.home() / ".config/solana/id.json"))
+ with path.open() as f:
+ keypair: List[int] = json.load(f)
+ return cls(Keypair.from_bytes(keypair))
+
+ @classmethod
+ def dummy(cls) -> Wallet:
+ """Create a dummy wallet instance that won't be used to sign transactions."""
+ keypair = Keypair.from_bytes([0] * 64)
+ return cls(keypair)
diff --git a/basics/anchorpy-main/src/anchorpy/py.typed b/basics/anchorpy-main/src/anchorpy/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/basics/anchorpy-main/src/anchorpy/pytest_plugin.py b/basics/anchorpy-main/src/anchorpy/pytest_plugin.py
new file mode 100644
index 0000000..ba876ff
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/pytest_plugin.py
@@ -0,0 +1,296 @@
+"""This module provides the `localnet_fixture` fixture factory."""
+import os
+import signal
+import subprocess
+from contextlib import suppress
+from pathlib import Path
+from typing import AsyncGenerator, Callable, Literal, Optional, Sequence, Tuple, Union
+
+from pytest import fixture
+from pytest_asyncio import fixture as async_fixture
+from pytest_xprocess import getrootdir
+from solders.account import Account
+from solders.pubkey import Pubkey
+from xprocess import ProcessStarter, XProcess, XProcessInfo
+
+from anchorpy.program.core import Program
+from anchorpy.workspace import close_workspace, create_workspace
+
+with suppress(ImportError):
+ from solders import bankrun
+
+_Scope = Literal["session", "package", "module", "class", "function"]
+
+
+class _FixedXProcessInfo(XProcessInfo):
+ def terminate(self, timeout=60): # noqa: ARG002
+ if not self.pid:
+ return 0
+ try:
+ pgid = os.getpgid(self.pid)
+ except ProcessLookupError:
+ return 0
+ try:
+ os.killpg(pgid, signal.SIGTERM)
+ except OSError as err:
+ print(f"Error while terminating process {err}")
+ return -1
+ return 1
+
+
+class _FixedXProcess(XProcess):
+ def getinfo(self, name: str) -> _FixedXProcessInfo:
+ """Return Process Info for the given external process.
+
+ Args:
+ name: Name of the external process.
+ """
+ return _FixedXProcessInfo(self.rootdir, name)
+
+ def ensure(
+ self, name: str, preparefunc: ProcessStarter, restart: bool = False
+ ) -> tuple:
+ """Return (PID, logfile) from a newly started or already running process.
+
+ Args:
+ name: Name of the external process, used for caching info across test runs.
+ preparefunc: A subclass of ProcessStarter.
+ restart: Force restarting the process if it is running.
+
+ Raises:
+ RuntimeError: If process fails to start within the required time.
+
+ Returns:
+ (PID, logfile) logfile will be seeked to the end if the
+ server was running, otherwise seeked to the line after
+ where the wait pattern matched.
+ """
+ info = self.getinfo(name)
+ if not restart and not info.isrunning():
+ restart = True
+
+ if restart:
+ # ensure the process is terminated first
+ if info.pid is not None:
+ info.terminate()
+
+ controldir = info.controldir.ensure(dir=1)
+ starter = preparefunc(controldir, self)
+ args = [str(x) for x in starter.args]
+ self.log.debug("%s$ %s", controldir, " ".join(args))
+ stdout = open(str(info.logpath), "wb", 0) # noqa: SIM115
+
+ # is env still necessary? we could pass all in popen_kwargs
+ kwargs = {"env": starter.env}
+
+ popen_kwargs = {
+ "stdout": stdout,
+ "stderr": subprocess.STDOUT,
+ # this gives the user the ability to
+ # override the previous keywords if
+ # desired
+ **starter.popen_kwargs,
+ }
+
+ kwargs["close_fds"] = True
+
+ # keep references of all popen
+ # and info objects for cleanup
+ self._info_objects.append((info, starter.terminate_on_interrupt))
+ popen_instance = subprocess.Popen(
+ args,
+ **popen_kwargs,
+ **kwargs, # type: ignore
+ )
+ self._popen_instances.append(popen_instance)
+
+ info.pid = pid = self._popen_instances[-1].pid
+ info.pidpath.write(str(pid))
+ self.log.debug("process %r started pid=%s", name, pid)
+ stdout.close()
+
+ # keep track of all file handles so we can
+ # cleanup later during teardown phase
+ self._file_handles.append(info.logpath.open())
+
+ if not restart:
+ self._file_handles[-1].seek(0, 2)
+ else:
+ if not starter.wait(self._file_handles[-1]):
+ raise RuntimeError(
+ f"Could not start process {name}, the specified "
+ f"log pattern was not found within {starter.max_read_lines} lines."
+ )
+ self.log.debug("%s process startup detected", name)
+
+ pytest_extlogfiles = self.config.__dict__.setdefault("_extlogfiles", {})
+ pytest_extlogfiles[name] = self._file_handles[-1]
+ self.getinfo(name)
+
+ return info.pid, info.logpath
+
+
+@async_fixture(scope="session")
+def _fixed_xprocess(request):
+ """Yield session-scoped XProcess helper to manage long-running processes required for testing.""" # noqa: E501
+ rootdir = getrootdir(request.config)
+ with _FixedXProcess(request.config, rootdir) as xproc:
+ # pass in xprocess object into pytest_unconfigure
+ # through config for proper cleanup during teardown
+ request.config._xprocess = xproc
+ yield xproc
+
+
+def localnet_fixture(
+ path: Path,
+ scope: _Scope = "module",
+ timeout_seconds: int = 60,
+ build_cmd: Optional[str] = None,
+) -> Callable:
+ """Create a fixture that sets up and tears down a localnet instance with workspace programs deployed.
+
+ Args:
+ path: Path to root of the Anchor project.
+ scope: Pytest fixture scope.
+ timeout_seconds: Time to wait for Anchor localnet to start.
+ build_cmd: Command to run before `anchor localnet`. Defaults to `anchor build`.
+
+ Returns:
+ A localnet fixture for use with pytest.
+ """ # noqa: E501,D202
+
+ @fixture(scope=scope)
+ def _localnet_fixture(_fixed_xprocess):
+ class Starter(ProcessStarter):
+ # startup pattern
+ pattern = "JSON RPC URL"
+ terminate_on_interrupt = True
+ # command to start process
+ args = ["anchor", "localnet", "--skip-build"]
+ timeout = timeout_seconds
+ popen_kwargs = {
+ "cwd": path,
+ "start_new_session": True,
+ }
+ max_read_lines = 1_000
+ # command to start process
+
+ actual_build_cmd = "anchor build" if build_cmd is None else build_cmd
+ subprocess.run(actual_build_cmd, cwd=path, check=True, shell=True)
+ # ensure process is running and return its logfile
+ logfile = _fixed_xprocess.ensure("localnet", Starter)
+
+ yield logfile
+
+ # clean up whole process tree afterwards
+ _fixed_xprocess.getinfo("localnet").terminate()
+
+ return _localnet_fixture
+
+
+# Should figure out how to reuse localnet_fixture
+# instead of copy-pasting (Pytest didn't like it).
+def workspace_fixture(
+ path: Union[Path, str],
+ scope: _Scope = "module",
+ timeout_seconds: int = 60,
+ build_cmd: Optional[str] = None,
+) -> Callable:
+ """Create a fixture that sets up and tears down a localnet instance and returns a workspace dict.
+
+ Equivalent to combining `localnet_fixture`, `create_workspace` and `close_workspace`.
+
+ Args:
+ path: Path to root of the Anchor project.
+ scope: Pytest fixture scope.
+ timeout_seconds: Time to wait for Anchor localnet to start.
+ build_cmd: Command to run before `anchor localnet`. Defaults to `anchor build`.
+
+ Returns:
+ A workspace fixture for use with pytest.
+ """ # noqa: E501,D202
+
+ @async_fixture(scope=scope)
+ async def _workspace_fixture(
+ _fixed_xprocess,
+ ) -> AsyncGenerator[dict[str, Program], None]:
+ class Starter(ProcessStarter):
+ # startup pattern
+ pattern = "JSON RPC URL"
+ terminate_on_interrupt = True
+ # command to start process
+ args = ["anchor", "localnet", "--skip-build"]
+ timeout = timeout_seconds
+ popen_kwargs = {
+ "cwd": path,
+ "start_new_session": True,
+ }
+ max_read_lines = 1_000
+ # command to start process
+
+ actual_build_cmd = "anchor build" if build_cmd is None else build_cmd
+ subprocess.run(actual_build_cmd, cwd=path, check=True, shell=True)
+ # ensure process is running
+ _ = _fixed_xprocess.ensure("localnet", Starter)
+ ws = create_workspace(path)
+ yield ws
+ await close_workspace(ws)
+
+ # clean up whole process tree afterwards
+ _fixed_xprocess.getinfo("localnet").terminate()
+
+ return _workspace_fixture
+
+
+async def _bankrun_helper(
+ path: Union[Path, str],
+ build_cmd: Optional[str] = None,
+ accounts: Optional[Sequence[Tuple[Pubkey, Account]]] = None,
+ compute_max_units: Optional[int] = None,
+ transaction_account_lock_limit: Optional[int] = None,
+) -> "bankrun.ProgramTestContext":
+ actual_build_cmd = "anchor build" if build_cmd is None else build_cmd
+ subprocess.run(actual_build_cmd, cwd=path, check=True, shell=True)
+ path_to_use = Path(path)
+ return await bankrun.start_anchor(
+ path_to_use,
+ accounts=accounts,
+ compute_max_units=compute_max_units,
+ transaction_account_lock_limit=transaction_account_lock_limit,
+ )
+
+
+def bankrun_fixture(
+ path: Union[Path, str],
+ scope: _Scope = "module",
+ build_cmd: Optional[str] = None,
+ accounts: Optional[Sequence[Tuple[Pubkey, Account]]] = None,
+ compute_max_units: Optional[int] = None,
+ transaction_account_lock_limit: Optional[int] = None,
+) -> "bankrun.ProgramTestContext":
+ """Create a fixture that builds the project and starts a bankrun with all the programs in the workspace deployed.
+
+ Args:
+ path: Path to root of the Anchor project.
+ scope: Pytest fixture scope.
+ build_cmd: Command to build the project. Defaults to `anchor build`.
+ accounts: A sequence of (address, account_object) tuples, indicating
+ what data to write to the given addresses.
+ compute_max_units: Override the default compute unit limit for a transaction.
+ transaction_account_lock_limit: Override the default transaction account lock limit.
+
+ Returns:
+ A bankrun fixture for use with pytest.
+ """ # noqa: E501,D202
+
+ @async_fixture(scope=scope)
+ async def _bankrun_fixture() -> bankrun.ProgramTestContext:
+ return await _bankrun_helper(
+ path,
+ build_cmd,
+ accounts,
+ compute_max_units,
+ transaction_account_lock_limit,
+ )
+
+ return _bankrun_fixture
diff --git a/basics/anchorpy-main/src/anchorpy/template.py b/basics/anchorpy-main/src/anchorpy/template.py
new file mode 100644
index 0000000..cf0a1ad
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/template.py
@@ -0,0 +1,31 @@
+INIT_TESTS = '''"""AnchorPy integration tests."""
+import asyncio
+from pytest import fixture, mark
+
+from anchorpy import Program
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+
+
+@fixture(scope="module")
+def event_loop():
+ """Create a module-scoped event loop so we can use module-scope async fixtures."""
+ loop = asyncio.get_event_loop_policy().new_event_loop() # noqa: DAR301
+ yield loop
+ loop.close()
+
+
+workspace = workspace_fixture(".")
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ """Create a Program instance."""
+ return workspace["{}"]
+
+
+@mark.asyncio
+async def test_init(program: Program) -> None:
+ """Test that the initialize function is invoked successfully."""
+ await program.rpc["initialize"]()
+'''
diff --git a/basics/anchorpy-main/src/anchorpy/utils/__init__.py b/basics/anchorpy-main/src/anchorpy/utils/__init__.py
new file mode 100644
index 0000000..d701d15
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/utils/__init__.py
@@ -0,0 +1,4 @@
+"""Various utility functions."""
+from anchorpy.utils import rpc, token
+
+__all__ = ["rpc", "token"]
diff --git a/basics/anchorpy-main/src/anchorpy/utils/rpc.py b/basics/anchorpy-main/src/anchorpy/utils/rpc.py
new file mode 100644
index 0000000..12ab015
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/utils/rpc.py
@@ -0,0 +1,157 @@
+"""This module contains the invoke function."""
+from asyncio import gather
+from base64 import b64decode
+from dataclasses import dataclass
+from typing import Any, NamedTuple, Optional
+
+import jsonrpcclient
+import zstandard
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+from solana.rpc.core import RPCException
+from solana.transaction import Transaction
+from solders.instruction import AccountMeta, Instruction
+from solders.pubkey import Pubkey
+from solders.signature import Signature
+from toolz import concat, partition_all
+
+from anchorpy.program.common import AddressType, translate_address
+from anchorpy.provider import Provider
+
+_GET_MULTIPLE_ACCOUNTS_LIMIT = 100
+_MAX_ACCOUNT_SIZE = 10 * 1048576
+
+
+class AccountInfo(NamedTuple):
+ """Information describing an account.
+
+ Attributes:
+ executable: `True` if this account's data contains a loaded program.
+ owner: Identifier of the program that owns the account.
+ lamports: Number of lamports assigned to the account.
+ data: Optional data assigned to the account.
+ rent_epoch: Optional rent epoch info for for account.
+ """
+
+ executable: bool
+ owner: Pubkey
+ lamports: int
+ data: bytes
+ rent_epoch: Optional[int]
+
+
+async def invoke(
+ program_id: AddressType,
+ provider: Provider,
+ accounts: Optional[list[AccountMeta]] = None,
+ data: Optional[bytes] = None,
+) -> Signature:
+ """Send a transaction to a program with the given accounts and instruction data.
+
+ Args:
+ program_id: The program ID
+ provider: the `Provider` instance.
+ accounts: `AccountMeta` objects.
+ data: The transaction data.
+
+ Returns:
+ The transaction signature.
+ """
+ translated_program_id = translate_address(program_id)
+ tx = Transaction()
+ tx.add(
+ Instruction(
+ program_id=translated_program_id,
+ accounts=[] if accounts is None else accounts,
+ data=bytes(0) if data is None else data,
+ ),
+ )
+ return await provider.send(tx)
+
+
+@dataclass
+class _MultipleAccountsItem:
+ pubkey: Pubkey
+ account: AccountInfo
+
+
+async def get_multiple_accounts(
+ connection: AsyncClient,
+ pubkeys: list[Pubkey],
+ batch_size: int = 3,
+ commitment: Optional[Commitment] = None,
+) -> list[Optional[_MultipleAccountsItem]]:
+ """Fetch multiple account infos through batched `getMultipleAccount` RPC requests.
+
+ Args:
+ connection: The `solana-py` client object.
+ pubkeys: Pubkeys to fetch.
+ batch_size: The number of `getMultipleAccount` objects to include in each
+ HTTP request.
+ commitment: Bank state to query.
+
+ Returns:
+ Account infos and pubkeys.
+ """
+ pubkeys_per_network_request = _GET_MULTIPLE_ACCOUNTS_LIMIT * batch_size
+ chunks = partition_all(pubkeys_per_network_request, pubkeys)
+ awaitables = [
+ _get_multiple_accounts_core(connection, pubkeys_chunk, commitment)
+ for pubkeys_chunk in chunks
+ ]
+ results = await gather(*awaitables, return_exceptions=False)
+ return list(concat(results))
+
+
+async def _get_multiple_accounts_core(
+ connection: AsyncClient, pubkeys: list[Pubkey], commitment: Optional[Commitment]
+) -> list[Optional[_MultipleAccountsItem]]:
+ pubkey_batches = partition_all(_GET_MULTIPLE_ACCOUNTS_LIMIT, pubkeys)
+ rpc_requests: list[dict[str, Any]] = []
+ commitment_to_use = connection._commitment if commitment is None else commitment
+ for pubkey_batch in pubkey_batches:
+ pubkeys_to_send = [str(pubkey) for pubkey in pubkey_batch]
+ rpc_request = jsonrpcclient.request(
+ "getMultipleAccounts",
+ params=[
+ pubkeys_to_send,
+ {"encoding": "base64+zstd", "commitment": commitment_to_use},
+ ],
+ )
+ rpc_requests.append(rpc_request)
+ resp = await connection._provider.session.post(
+ connection._provider.endpoint_uri,
+ json=rpc_requests,
+ headers={"content-encoding": "gzip"},
+ )
+ parsed = jsonrpcclient.parse(resp.json())
+ result: list[Optional[_MultipleAccountsItem]] = []
+ dctx = zstandard.ZstdDecompressor()
+ idx = 0
+ for rpc_result in parsed:
+ if isinstance(rpc_result, jsonrpcclient.Error):
+ raise RPCException(
+ f"Failed to get info about accounts: {rpc_result.message}"
+ )
+ for account in rpc_result.result["value"]:
+ if account is None:
+ result.append(None)
+ else:
+ acc_info_data = account["data"][0]
+ decoded = b64decode(acc_info_data)
+ decompressed = dctx.decompress(
+ decoded, max_output_size=_MAX_ACCOUNT_SIZE
+ )
+ acc_info = AccountInfo(
+ executable=account["executable"],
+ owner=Pubkey.from_string(account["owner"]),
+ lamports=account["lamports"],
+ data=decompressed,
+ rent_epoch=account["rentEpoch"],
+ )
+ multiple_accounts_item = _MultipleAccountsItem(
+ pubkey=pubkeys[idx], account=acc_info
+ )
+ result.append(multiple_accounts_item)
+ idx += 1
+ return result
diff --git a/basics/anchorpy-main/src/anchorpy/utils/token.py b/basics/anchorpy-main/src/anchorpy/utils/token.py
new file mode 100644
index 0000000..1289478
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/utils/token.py
@@ -0,0 +1,318 @@
+"""This module contains utilities for the SPL Token Program."""
+from typing import Optional
+
+from solana.rpc.commitment import Confirmed
+from solders.instruction import Instruction
+from solders.keypair import Keypair
+from solders.message import Message
+from solders.pubkey import Pubkey
+from solders.rpc.responses import GetAccountInfoResp
+from solders.system_program import CreateAccountParams, create_account
+from solders.transaction import VersionedTransaction
+from spl.token._layouts import ACCOUNT_LAYOUT, MINT_LAYOUT
+from spl.token.async_client import AsyncToken
+from spl.token.constants import TOKEN_PROGRAM_ID
+from spl.token.core import AccountInfo, MintInfo
+from spl.token.instructions import (
+ InitializeAccountParams,
+ InitializeMintParams,
+ MintToParams,
+ initialize_account,
+ initialize_mint,
+ mint_to,
+)
+
+from anchorpy.provider import Provider
+
+
+async def create_token_account(
+ prov: Provider,
+ mint: Pubkey,
+ owner: Pubkey,
+) -> Pubkey:
+ """Create a token account.
+
+ Args:
+ prov: An anchorpy Provider instance.
+ mint: The pubkey of the token's mint.
+ owner: User account that will own the new account.
+
+ Returns:
+ The pubkey of the new account.
+ """
+ token = AsyncToken(prov.connection, mint, TOKEN_PROGRAM_ID, prov.wallet.payer)
+ return await token.create_account(owner)
+
+
+async def create_token_account_instrs(
+ provider: Provider,
+ new_account_pubkey: Pubkey,
+ mint: Pubkey,
+ owner: Pubkey,
+) -> tuple[Instruction, Instruction]:
+ """Generate instructions for creating a token account.
+
+ Args:
+ provider: An anchorpy Provider instance.
+ new_account_pubkey: The pubkey of the new account.
+ mint: The pubkey of the token's mint.
+ owner: User account that will own the new account.
+
+ Returns:
+ Transaction instructions to create the new account.
+ """
+ mbre_resp = await provider.connection.get_minimum_balance_for_rent_exemption(165)
+ lamports = mbre_resp.value
+ return (
+ create_account(
+ CreateAccountParams(
+ from_pubkey=provider.wallet.public_key,
+ to_pubkey=new_account_pubkey,
+ space=165,
+ lamports=lamports,
+ owner=TOKEN_PROGRAM_ID,
+ )
+ ),
+ initialize_account(
+ InitializeAccountParams(
+ account=new_account_pubkey,
+ mint=mint,
+ owner=owner,
+ program_id=TOKEN_PROGRAM_ID,
+ )
+ ),
+ )
+
+
+async def create_mint_and_vault(
+ provider: Provider,
+ amount: int,
+ owner: Optional[Pubkey] = None,
+ decimals: Optional[int] = None,
+) -> tuple[Pubkey, Pubkey]:
+ """Create a mint and a vault, then mint tokens to the vault.
+
+ Args:
+ provider: An anchorpy Provider instance.
+ amount: The amount of tokens to mint to the vault.
+ owner: User account that will own the new account.
+ decimals: The number of decimal places for the token to support.
+
+ Returns:
+ The mint and vault pubkeys.
+ """
+ actual_owner = provider.wallet.public_key if owner is None else owner
+ mint = Keypair()
+ vault = Keypair()
+ mint_space = 82
+ create_mint_mbre_resp = (
+ await provider.connection.get_minimum_balance_for_rent_exemption(mint_space)
+ )
+ create_mint_mbre = create_mint_mbre_resp.value
+ create_mint_account_params = CreateAccountParams(
+ from_pubkey=provider.wallet.public_key,
+ to_pubkey=mint.pubkey(),
+ space=mint_space,
+ lamports=create_mint_mbre,
+ owner=TOKEN_PROGRAM_ID,
+ )
+ create_mint_account_instruction = create_account(
+ create_mint_account_params,
+ )
+ init_mint_instruction = initialize_mint(
+ InitializeMintParams(
+ mint=mint.pubkey(),
+ decimals=0 if decimals is None else decimals,
+ mint_authority=provider.wallet.public_key,
+ program_id=TOKEN_PROGRAM_ID,
+ ),
+ )
+ vault_space = 165
+ create_vault_mbre_resp = (
+ await provider.connection.get_minimum_balance_for_rent_exemption(vault_space)
+ )
+ create_vault_mbre = create_vault_mbre_resp.value
+ create_vault_account_instruction = create_account(
+ CreateAccountParams(
+ from_pubkey=provider.wallet.public_key,
+ to_pubkey=vault.pubkey(),
+ space=vault_space,
+ lamports=create_vault_mbre,
+ owner=TOKEN_PROGRAM_ID,
+ ),
+ )
+ init_vault_instruction = initialize_account(
+ InitializeAccountParams(
+ program_id=TOKEN_PROGRAM_ID,
+ account=vault.pubkey(),
+ mint=mint.pubkey(),
+ owner=actual_owner,
+ ),
+ )
+ mint_to_instruction = mint_to(
+ MintToParams(
+ program_id=TOKEN_PROGRAM_ID,
+ mint=mint.pubkey(),
+ dest=vault.pubkey(),
+ amount=amount,
+ mint_authority=provider.wallet.public_key,
+ ),
+ )
+ blockhash = (
+ await provider.connection.get_latest_blockhash(Confirmed)
+ ).value.blockhash
+ msg = Message.new_with_blockhash(
+ [
+ create_mint_account_instruction,
+ init_mint_instruction,
+ create_vault_account_instruction,
+ init_vault_instruction,
+ mint_to_instruction,
+ ],
+ provider.wallet.public_key,
+ blockhash,
+ )
+ tx = VersionedTransaction(msg, [provider.wallet.payer, mint, vault])
+ await provider.send(tx)
+ return mint.pubkey(), vault.pubkey()
+
+
+def parse_token_account(info: GetAccountInfoResp) -> AccountInfo:
+ """Parse `AccountInfo` from RPC response.
+
+ Args:
+ info: the `get_account_info` RPC response.
+
+ Raises:
+ ValueError: If the fetched data is the wrong size.
+ AttributeError: If the account is not owned by the token program.
+
+ Returns:
+ The parsed `AccountInfo`.
+ """
+ val = info.value
+ if not val:
+ raise ValueError("Invalid account owner")
+
+ if val.owner != TOKEN_PROGRAM_ID:
+ raise AttributeError("Invalid account owner")
+
+ bytes_data = val.data
+ if len(bytes_data) != ACCOUNT_LAYOUT.sizeof():
+ raise ValueError("Invalid account size")
+
+ decoded_data = ACCOUNT_LAYOUT.parse(bytes_data)
+
+ mint = Pubkey(decoded_data.mint)
+ owner = Pubkey(decoded_data.owner)
+ amount = decoded_data.amount
+
+ if decoded_data.delegate_option == 0:
+ delegate = None
+ delegated_amount = 0
+ else:
+ delegate = Pubkey(decoded_data.delegate)
+ delegated_amount = decoded_data.delegated_amount
+
+ is_initialized = decoded_data.state != 0
+ is_frozen = decoded_data.state == 2
+
+ if decoded_data.is_native_option == 1:
+ rent_exempt_reserve = decoded_data.is_native
+ is_native = True
+ else:
+ rent_exempt_reserve = None
+ is_native = False
+
+ if decoded_data.close_authority_option == 0:
+ close_authority = None
+ else:
+ close_authority = Pubkey(decoded_data.owner)
+
+ return AccountInfo(
+ mint,
+ owner,
+ amount,
+ delegate,
+ delegated_amount,
+ is_initialized,
+ is_frozen,
+ is_native,
+ rent_exempt_reserve,
+ close_authority,
+ )
+
+
+async def get_token_account(provider: Provider, addr: Pubkey) -> AccountInfo:
+ """Retrieve token account information.
+
+ Args:
+ provider: The anchorpy Provider instance.
+ addr: The pubkey of the token account.
+
+ Returns:
+ The parsed `AccountInfo` of the token account.
+ """
+ depositor_acc_info_raw = await provider.connection.get_account_info(addr)
+ return parse_token_account(depositor_acc_info_raw)
+
+
+async def get_mint_info(
+ provider: Provider,
+ addr: Pubkey,
+) -> MintInfo:
+ """Retrieve mint information.
+
+ Args:
+ provider: The anchorpy Provider instance.
+ addr: The pubkey of the mint.
+
+ Returns:
+ The parsed `MintInfo`.
+ """
+ depositor_acc_info_raw = await provider.connection.get_account_info(addr)
+ return parse_mint_account(depositor_acc_info_raw)
+
+
+def parse_mint_account(info: GetAccountInfoResp) -> MintInfo:
+ """Parse raw RPC response into `MintInfo`.
+
+ Args:
+ info: The RPC response from calling `.get_account_info` for the mint pubkey.
+
+ Raises:
+ AttributeError: If the account is not owned by the Token Program.
+ ValueError: If the fetched data is the wrong size.
+
+ Returns:
+ The parsed `MintInfo`.
+ """
+ val = info.value
+ if val is None:
+ raise ValueError("Account does not exist.")
+ owner = val.owner
+ if owner != TOKEN_PROGRAM_ID:
+ raise AttributeError(f"Invalid mint owner: {owner}")
+
+ bytes_data = val.data
+ if len(bytes_data) != MINT_LAYOUT.sizeof():
+ raise ValueError("Invalid mint size")
+
+ decoded_data = MINT_LAYOUT.parse(bytes_data)
+ decimals = decoded_data.decimals
+
+ mint_authority = (
+ None
+ if decoded_data.mint_authority_option == 0
+ else Pubkey(decoded_data.mint_authority)
+ )
+
+ supply = decoded_data.supply
+ is_initialized = decoded_data.is_initialized != 0
+
+ if decoded_data.freeze_authority_option == 0:
+ freeze_authority = None
+ else:
+ freeze_authority = Pubkey(decoded_data.freeze_authority)
+
+ return MintInfo(mint_authority, supply, decimals, is_initialized, freeze_authority)
diff --git a/basics/anchorpy-main/src/anchorpy/workspace.py b/basics/anchorpy-main/src/anchorpy/workspace.py
new file mode 100644
index 0000000..276015c
--- /dev/null
+++ b/basics/anchorpy-main/src/anchorpy/workspace.py
@@ -0,0 +1,52 @@
+"""This module contains code for creating the Anchor workspace."""
+from pathlib import Path
+from typing import Dict, Optional, Union
+
+import toml # type: ignore
+from anchorpy_core.idl import Idl
+from solders.pubkey import Pubkey
+
+from anchorpy.program.core import Program
+from anchorpy.provider import Provider
+
+WorkspaceType = Dict[str, Program]
+
+
+def create_workspace(
+ path: Optional[Union[Path, str]] = None, url: Optional[str] = None
+) -> WorkspaceType:
+ """Get a workspace from the provided path to the project root.
+
+ Args:
+ path: The path to the project root. Defaults to the current working
+ directory if omitted.
+ url: The URL of the JSON RPC. Defaults to http://localhost:8899.
+
+ Returns:
+ Mapping of program name to Program object.
+ """
+ result = {}
+ project_root = Path.cwd() if path is None else Path(path)
+ idl_folder = project_root / "target/idl"
+ localnet_programs: dict[str, str] = toml.load(project_root / "Anchor.toml")[
+ "programs"
+ ]["localnet"]
+ for file in idl_folder.iterdir():
+ raw = file.read_text()
+ idl = Idl.from_json(raw)
+ name = idl.name
+ program_id = Pubkey.from_string(localnet_programs[name])
+ program = Program(idl, program_id, Provider.local(url))
+ result[idl.name] = program
+ return result
+
+
+async def close_workspace(workspace: WorkspaceType) -> None:
+ """Close the HTTP clients of all the programs in the workspace.
+
+ Args:
+ workspace: The workspace to close.
+ """
+ for program in workspace.values():
+ # could do this in a faster way but there's probably no point.
+ await program.close()
diff --git a/basics/anchorpy-main/tests/__init__.py b/basics/anchorpy-main/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/basics/anchorpy-main/tests/client-gen/__init__.py b/basics/anchorpy-main/tests/client-gen/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/basics/anchorpy-main/tests/client-gen/example-program/Anchor.toml b/basics/anchorpy-main/tests/client-gen/example-program/Anchor.toml
new file mode 100644
index 0000000..d6d5c12
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example-program/Anchor.toml
@@ -0,0 +1,12 @@
+[programs.localnet]
+example_program = "3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8"
+
+[registry]
+url = "https://anchor.projectserum.com"
+
+[provider]
+cluster = "localnet"
+wallet = "~/.config/solana/id.json"
+
+[features]
+seeds = true
diff --git a/basics/anchorpy-main/tests/client-gen/example-program/Cargo.lock b/basics/anchorpy-main/tests/client-gen/example-program/Cargo.lock
new file mode 100644
index 0000000..17ca9f0
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example-program/Cargo.lock
@@ -0,0 +1,1562 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ahash"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+dependencies = [
+ "getrandom 0.2.7",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anchor-attribute-access-control"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf7d535e1381be3de2c0716c0a1c1e32ad9df1042cddcf7bc18d743569e53319"
+dependencies = [
+ "anchor-syn",
+ "anyhow",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "anchor-attribute-account"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3bcd731f21048a032be27c7791701120e44f3f6371358fc4261a7f716283d29"
+dependencies = [
+ "anchor-syn",
+ "anyhow",
+ "bs58 0.4.0",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "anchor-attribute-constant"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1be64a48e395fe00b8217287f226078be2cf32dae42fdf8a885b997945c3d28"
+dependencies = [
+ "anchor-syn",
+ "proc-macro2",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "anchor-attribute-error"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38ea6713d1938c0da03656ff8a693b17dc0396da66d1ba320557f07e86eca0d4"
+dependencies = [
+ "anchor-syn",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "anchor-attribute-event"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d401f11efb3644285685f8339829a9786d43ed7490bb1699f33c478d04d5a582"
+dependencies = [
+ "anchor-syn",
+ "anyhow",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "anchor-attribute-interface"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6700a6f5c888a9c33fe8afc0c64fd8575fa28d05446037306d0f96102ae4480"
+dependencies = [
+ "anchor-syn",
+ "anyhow",
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "anchor-attribute-program"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ad769993b5266714e8939e47fbdede90e5c030333c7522d99a4d4748cf26712"
+dependencies = [
+ "anchor-syn",
+ "anyhow",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "anchor-attribute-state"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e677fae4a016a554acdd0e3b7f178d3acafaa7e7ffac6b8690cf4e171f1c116"
+dependencies = [
+ "anchor-syn",
+ "anyhow",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "anchor-derive-accounts"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "340beef6809d1c3fcc7ae219153d981e95a8a277ff31985bd7050e32645dc9a8"
+dependencies = [
+ "anchor-syn",
+ "anyhow",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "anchor-lang"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "662ceafe667448ee4199a4be2ee83b6bb76da28566eee5cea05f96ab38255af8"
+dependencies = [
+ "anchor-attribute-access-control",
+ "anchor-attribute-account",
+ "anchor-attribute-constant",
+ "anchor-attribute-error",
+ "anchor-attribute-event",
+ "anchor-attribute-interface",
+ "anchor-attribute-program",
+ "anchor-attribute-state",
+ "anchor-derive-accounts",
+ "arrayref",
+ "base64 0.13.0",
+ "bincode",
+ "borsh",
+ "bytemuck",
+ "solana-program",
+ "thiserror",
+]
+
+[[package]]
+name = "anchor-syn"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0418bcb5daac3b8cb1b60d8fdb1d468ca36f5509f31fb51179326fae1028fdcc"
+dependencies = [
+ "anyhow",
+ "bs58 0.3.1",
+ "heck",
+ "proc-macro2",
+ "proc-macro2-diagnostics",
+ "quote",
+ "serde",
+ "serde_json",
+ "sha2 0.9.9",
+ "syn 1.0.102",
+ "thiserror",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.65"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
+
+[[package]]
+name = "arrayref"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "base64"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
+
+[[package]]
+name = "base64"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitmaps"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "blake3"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "cc",
+ "cfg-if",
+ "constant_time_eq",
+ "digest 0.10.5",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "block-padding",
+ "generic-array",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
+
+[[package]]
+name = "borsh"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa"
+dependencies = [
+ "borsh-derive",
+ "hashbrown 0.11.2",
+]
+
+[[package]]
+name = "borsh-derive"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775"
+dependencies = [
+ "borsh-derive-internal",
+ "borsh-schema-derive-internal",
+ "proc-macro-crate",
+ "proc-macro2",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "borsh-derive-internal"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "borsh-schema-derive-internal"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "bs58"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb"
+
+[[package]]
+name = "bs58"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
+
+[[package]]
+name = "bumpalo"
+version = "3.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+
+[[package]]
+name = "bv"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340"
+dependencies = [
+ "feature-probe",
+ "serde",
+]
+
+[[package]]
+name = "bytemuck"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cc"
+version = "1.0.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+dependencies = [
+ "jobserver",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "console_error_panic_hook"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "console_log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494"
+dependencies = [
+ "log",
+ "web-sys",
+]
+
+[[package]]
+name = "constant_time_eq"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset 0.9.0",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "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 = "curve25519-dalek"
+version = "3.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0"
+dependencies = [
+ "byteorder",
+ "digest 0.9.0",
+ "rand_core 0.5.1",
+ "serde",
+ "subtle",
+ "zeroize",
+]
+
+[[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.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c"
+dependencies = [
+ "block-buffer 0.10.3",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "either"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+
+[[package]]
+name = "example-program"
+version = "0.1.0"
+dependencies = [
+ "anchor-lang",
+]
+
+[[package]]
+name = "feature-probe"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da"
+
+[[package]]
+name = "generic-array"
+version = "0.14.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
+dependencies = [
+ "serde",
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
+
+[[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-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",
+]
+
+[[package]]
+name = "im"
+version = "15.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9"
+dependencies = [
+ "bitmaps",
+ "rand_core 0.6.4",
+ "rand_xoshiro",
+ "rayon",
+ "serde",
+ "sized-chunks",
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
+
+[[package]]
+name = "jobserver"
+version = "0.1.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940"
+dependencies = [
+ "cpufeatures",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.135"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+
+[[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",
+ "hmac-drbg",
+ "libsecp256k1-core",
+ "libsecp256k1-gen-ecmult",
+ "libsecp256k1-gen-genmult",
+ "rand",
+ "serde",
+ "sha2 0.9.9",
+ "typenum",
+]
+
+[[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 = "lock_api"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "memmap2"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num-derive"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
+
+[[package]]
+name = "opaque-debug"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets",
+]
+
+[[package]]
+name = "pbkdf2"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd"
+dependencies = [
+ "crypto-mac",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
+name = "proc-macro-crate"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
+dependencies = [
+ "toml",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "proc-macro2-diagnostics"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+ "version_check",
+ "yansi",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
+dependencies = [
+ "proc-macro2",
+]
+
+[[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",
+ "rand_core 0.5.1",
+ "rand_hc",
+]
+
+[[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]]
+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]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom 0.2.7",
+]
+
+[[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 = "rand_xoshiro"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
+dependencies = [
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
+
+[[package]]
+name = "ryu"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "semver"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
+
+[[package]]
+name = "serde"
+version = "1.0.145"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_bytes"
+version = "0.11.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.145"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha2"
+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",
+ "digest 0.9.0",
+ "opaque-debug",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.10.5",
+]
+
+[[package]]
+name = "sha3"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
+dependencies = [
+ "digest 0.10.5",
+ "keccak",
+]
+
+[[package]]
+name = "sized-chunks"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
+dependencies = [
+ "bitmaps",
+ "typenum",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "solana-frozen-abi"
+version = "1.14.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a100b7fa8198c20354eb7256c0d9789107d8a62280221f3efe15f7c9dc4cec"
+dependencies = [
+ "ahash",
+ "blake3",
+ "block-buffer 0.9.0",
+ "bs58 0.4.0",
+ "bv",
+ "byteorder",
+ "cc",
+ "either",
+ "generic-array",
+ "getrandom 0.1.16",
+ "hashbrown 0.12.3",
+ "im",
+ "lazy_static",
+ "log",
+ "memmap2",
+ "once_cell",
+ "rand_core 0.6.4",
+ "rustc_version",
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "serde_json",
+ "sha2 0.10.6",
+ "solana-frozen-abi-macro",
+ "subtle",
+ "thiserror",
+]
+
+[[package]]
+name = "solana-frozen-abi-macro"
+version = "1.14.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f527f44601b35dd67d11bc72f2f7512976a466f9304ef574b87dac83ced8a42"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "solana-program"
+version = "1.14.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51ad5f48743ce505f6139a07e20aecdc689def12da7230fed661c2073ab97df8"
+dependencies = [
+ "base64 0.13.0",
+ "bincode",
+ "bitflags",
+ "blake3",
+ "borsh",
+ "borsh-derive",
+ "bs58 0.4.0",
+ "bv",
+ "bytemuck",
+ "cc",
+ "console_error_panic_hook",
+ "console_log",
+ "curve25519-dalek",
+ "getrandom 0.2.7",
+ "itertools",
+ "js-sys",
+ "lazy_static",
+ "libc",
+ "libsecp256k1",
+ "log",
+ "memoffset 0.6.5",
+ "num-derive",
+ "num-traits",
+ "parking_lot",
+ "rand",
+ "rand_chacha",
+ "rustc_version",
+ "rustversion",
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "serde_json",
+ "sha2 0.10.6",
+ "sha3",
+ "solana-frozen-abi",
+ "solana-frozen-abi-macro",
+ "solana-sdk-macro",
+ "thiserror",
+ "tiny-bip39",
+ "wasm-bindgen",
+ "zeroize",
+]
+
+[[package]]
+name = "solana-sdk-macro"
+version = "1.14.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bbc3ab3070c090e1a18fd5a0a07d729d0db2bc8524414dc3e16504286d38049"
+dependencies = [
+ "bs58 0.4.0",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
+[[package]]
+name = "syn"
+version = "1.0.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+]
+
+[[package]]
+name = "tiny-bip39"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d"
+dependencies = [
+ "anyhow",
+ "hmac",
+ "once_cell",
+ "pbkdf2",
+ "rand",
+ "rustc-hash",
+ "sha2 0.9.9",
+ "thiserror",
+ "unicode-normalization",
+ "wasm-bindgen",
+ "zeroize",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "toml"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "typenum"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.102",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+
+[[package]]
+name = "web-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
+[[package]]
+name = "yansi"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
+
+[[package]]
+name = "zeroize"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.26",
+]
diff --git a/basics/anchorpy-main/tests/client-gen/example-program/Cargo.toml b/basics/anchorpy-main/tests/client-gen/example-program/Cargo.toml
new file mode 100644
index 0000000..a60de98
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example-program/Cargo.toml
@@ -0,0 +1,4 @@
+[workspace]
+members = [
+ "programs/*"
+]
diff --git a/basics/anchorpy-main/tests/client-gen/example-program/programs/example-program/Cargo.toml b/basics/anchorpy-main/tests/client-gen/example-program/programs/example-program/Cargo.toml
new file mode 100644
index 0000000..c08202b
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example-program/programs/example-program/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "example-program"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2018"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "example_program"
+
+[features]
+no-entrypoint = []
+no-idl = []
+no-log-ix-name = []
+cpi = ["no-entrypoint"]
+default = []
+
+[dependencies]
+anchor-lang = "0.26.0"
diff --git a/basics/anchorpy-main/tests/client-gen/example-program/programs/example-program/Xargo.toml b/basics/anchorpy-main/tests/client-gen/example-program/programs/example-program/Xargo.toml
new file mode 100644
index 0000000..475fb71
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example-program/programs/example-program/Xargo.toml
@@ -0,0 +1,2 @@
+[target.bpfel-unknown-unknown.dependencies.std]
+features = []
diff --git a/basics/anchorpy-main/tests/client-gen/example-program/programs/example-program/src/lib.rs b/basics/anchorpy-main/tests/client-gen/example-program/programs/example-program/src/lib.rs
new file mode 100644
index 0000000..0875609
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example-program/programs/example-program/src/lib.rs
@@ -0,0 +1,351 @@
+use std::str::FromStr;
+
+use anchor_lang::prelude::*;
+
+declare_id!("3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8");
+
+pub const MY_SEED: [u8; 2] = *b"hi";
+pub const MY_SEED_STR: &str = "hi";
+pub const MY_SEED_U8: u8 = 1;
+pub const MY_SEED_U32: u32 = 2;
+pub const MY_SEED_U64: u64 = 3;
+
+#[program]
+pub mod example_program {
+ use super::*;
+
+ pub fn initialize(ctx: Context) -> Result<()> {
+ ctx.accounts.state.set_inner(State::default());
+ Ok(())
+ }
+
+ pub fn initialize_with_values(
+ ctx: Context,
+ bool_field: bool,
+ u8_field: u8,
+ i8_field: i8,
+ u16_field: u16,
+ i16_field: i16,
+ u32_field: u32,
+ i32_field: i32,
+ f32_field: f32,
+ u64_field: u64,
+ i64_field: i64,
+ f64_field: f64,
+ u128_field: u128,
+ i128_field: i128,
+ bytes_field: Vec,
+ string_field: String,
+ pubkey_field: Pubkey,
+ vec_field: Vec,
+ vec_struct_field: Vec,
+ option_field: Option,
+ option_struct_field: Option,
+ struct_field: FooStruct,
+ array_field: [bool; 3],
+ enum_field_1: FooEnum,
+ enum_field_2: FooEnum,
+ enum_field_3: FooEnum,
+ enum_field_4: FooEnum,
+ ) -> Result<()> {
+ ctx.accounts.state.set_inner(State {
+ bool_field,
+ u8_field,
+ i8_field,
+ u16_field,
+ i16_field,
+ u32_field,
+ i32_field,
+ f32_field,
+ u64_field,
+ i64_field,
+ f64_field,
+ u128_field,
+ i128_field,
+ bytes_field,
+ string_field,
+ pubkey_field,
+ vec_field,
+ vec_struct_field,
+ option_field,
+ option_struct_field,
+ struct_field,
+ array_field,
+ enum_field_1,
+ enum_field_2,
+ enum_field_3,
+ enum_field_4,
+ });
+
+ Ok(())
+ }
+
+ // a separate instruction due to initialize_with_values having too many arguments
+ // https://github.com/solana-labs/solana/issues/23978
+ pub fn initialize_with_values2(
+ ctx: Context,
+ vec_of_option: Vec>,
+ ) -> Result<()> {
+ ctx.accounts.state.set_inner(State2 { vec_of_option });
+ Ok(())
+ }
+
+ pub fn cause_error(_ctx: Context) -> Result<()> {
+ return Err(error!(ErrorCode::SomeError));
+ }
+
+ pub fn init_my_account(ctx: Context, _seed_a: u8) -> Result<()> {
+ ctx.accounts.account.data = 1337;
+ Ok(())
+ }
+
+ pub fn increment_state_when_present(ctx: Context) -> Result<()> {
+ if let Some(state) = ctx.accounts.first_state.as_mut() {
+ state.u8_field += 1;
+ }
+ Ok(())
+ }
+}
+
+#[derive(Accounts)]
+pub struct InitMyAccount<'info> {
+ base: Account<'info, BaseAccount>,
+ /// CHECK: shut up
+ base2: AccountInfo<'info>,
+ #[account(
+ seeds = [
+ "another-seed".as_bytes(),
+ b"test".as_ref(),
+ MY_SEED.as_ref(),
+ MY_SEED_STR.as_bytes(),
+ MY_SEED_U8.to_le_bytes().as_ref(),
+ &MY_SEED_U32.to_le_bytes(),
+ &MY_SEED_U64.to_le_bytes(),
+ ],
+ bump,
+ )]
+ account: Account<'info, MyAccount>,
+ nested: Nested<'info>,
+ system_program: Program<'info, System>,
+}
+
+#[derive(Accounts)]
+pub struct Nested<'info> {
+ #[account(
+ seeds = [
+ "nested-seed".as_bytes(),
+ b"test".as_ref(),
+ MY_SEED.as_ref(),
+ MY_SEED_STR.as_bytes(),
+ MY_SEED_U8.to_le_bytes().as_ref(),
+ &MY_SEED_U32.to_le_bytes(),
+ &MY_SEED_U64.to_le_bytes(),
+ ],
+ bump,
+ )]
+ /// CHECK: Not needed
+ account_nested: AccountInfo<'info>,
+}
+
+#[account]
+pub struct MyAccount {
+ data: u64,
+}
+
+#[account]
+pub struct BaseAccount {
+ base_data: u64,
+ base_data_key: Pubkey,
+}
+
+#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
+pub enum FooEnum {
+ Unnamed(bool, u8, BarStruct),
+ UnnamedSingle(BarStruct),
+ Named {
+ bool_field: bool,
+ u8_field: u8,
+ nested: BarStruct,
+ },
+ Struct(BarStruct),
+ OptionStruct(Option),
+ VecStruct(Vec),
+ NoFields,
+}
+
+#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
+pub struct BarStruct {
+ some_field: bool,
+ other_field: u8,
+}
+
+impl Default for BarStruct {
+ fn default() -> Self {
+ return BarStruct {
+ some_field: true,
+ other_field: 10,
+ };
+ }
+}
+
+#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
+pub struct FooStruct {
+ field1: u8,
+ field2: u16,
+ nested: BarStruct,
+ vec_nested: Vec,
+ option_nested: Option,
+ enum_field: FooEnum,
+}
+
+impl Default for FooStruct {
+ fn default() -> Self {
+ return FooStruct {
+ field1: 123,
+ field2: 999,
+ nested: BarStruct::default(),
+ vec_nested: vec![BarStruct::default()],
+ option_nested: Some(BarStruct::default()),
+ enum_field: FooEnum::Named {
+ bool_field: true,
+ u8_field: 15,
+ nested: BarStruct::default(),
+ },
+ };
+ }
+}
+
+#[account]
+pub struct State {
+ bool_field: bool,
+ u8_field: u8,
+ i8_field: i8,
+ u16_field: u16,
+ i16_field: i16,
+ u32_field: u32,
+ i32_field: i32,
+ f32_field: f32,
+ u64_field: u64,
+ i64_field: i64,
+ f64_field: f64,
+ u128_field: u128,
+ i128_field: i128,
+ bytes_field: Vec,
+ string_field: String,
+ pubkey_field: Pubkey,
+ vec_field: Vec,
+ vec_struct_field: Vec,
+ option_field: Option,
+ option_struct_field: Option,
+ struct_field: FooStruct,
+ array_field: [bool; 3],
+ enum_field_1: FooEnum,
+ enum_field_2: FooEnum,
+ enum_field_3: FooEnum,
+ enum_field_4: FooEnum,
+}
+
+impl Default for State {
+ fn default() -> Self {
+ // some arbitrary default values
+ return State {
+ bool_field: true,
+ u8_field: 234,
+ i8_field: -123,
+ u16_field: 62345,
+ i16_field: -31234,
+ u32_field: 1234567891,
+ i32_field: -1234567891,
+ f32_field: 123456.5,
+ u64_field: u64::MAX / 2 + 10,
+ i64_field: i64::MIN / 2 - 10,
+ f64_field: 1234567891.345,
+ u128_field: u128::MAX / 2 + 10,
+ i128_field: i128::MIN / 2 - 10,
+ bytes_field: vec![1, 2, 255, 254],
+ string_field: String::from("hello"),
+ pubkey_field: Pubkey::from_str("EPZP2wrcRtMxrAPJCXVEQaYD9eH7fH7h12YqKDcd4aS7").unwrap(),
+ vec_field: vec![1, 2, 100, 1000, u64::MAX],
+ vec_struct_field: vec![FooStruct::default()],
+ option_field: None,
+ option_struct_field: Some(FooStruct::default()),
+ struct_field: FooStruct::default(),
+ array_field: [true, false, true],
+ enum_field_1: FooEnum::Unnamed(false, 10, BarStruct::default()),
+ enum_field_2: FooEnum::Named {
+ bool_field: true,
+ u8_field: 20,
+ nested: BarStruct::default(),
+ },
+ enum_field_3: FooEnum::Struct(BarStruct::default()),
+ enum_field_4: FooEnum::NoFields,
+ };
+ }
+}
+
+#[account]
+pub struct State2 {
+ vec_of_option: Vec>,
+}
+impl Default for State2 {
+ fn default() -> Self {
+ return State2 {
+ vec_of_option: vec![None, Some(10)],
+ };
+ }
+}
+
+#[derive(Accounts)]
+pub struct NestedAccounts<'info> {
+ clock: Sysvar<'info, Clock>,
+ rent: Sysvar<'info, Rent>,
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+ #[account(
+ init,
+ space = 8 + 1000, // TODO: use exact space required
+ payer = payer,
+ )]
+ state: Account<'info, State>,
+
+ nested: NestedAccounts<'info>,
+
+ #[account(mut)]
+ payer: Signer<'info>,
+ system_program: Program<'info, System>,
+}
+
+#[derive(Accounts)]
+pub struct Initialize2<'info> {
+ #[account(
+ init,
+ space = 8 + 1000, // TODO: use exact space required
+ payer = payer,
+ )]
+ state: Account<'info, State2>,
+
+ #[account(mut)]
+ payer: Signer<'info>,
+ system_program: Program<'info, System>,
+}
+
+#[derive(Accounts)]
+pub struct IncrementStateWhenPresent<'info> {
+ #[account(mut)]
+ first_state: Option>,
+ second_state: Account<'info, State2>,
+ system_program: Program<'info, System>,
+}
+
+#[derive(Accounts)]
+pub struct CauseError {}
+
+#[error_code]
+pub enum ErrorCode {
+ #[msg("Example error.")]
+ SomeError,
+ #[msg("Another error.")]
+ OtherError,
+}
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/__init__.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/__init__.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/__init__.py
new file mode 100644
index 0000000..69f5a39
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/__init__.py
@@ -0,0 +1,4 @@
+from .my_account import MyAccount, MyAccountJSON
+from .base_account import BaseAccount, BaseAccountJSON
+from .state import State, StateJSON
+from .state2 import State2, State2JSON
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/base_account.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/base_account.py
new file mode 100644
index 0000000..b3978ca
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/base_account.py
@@ -0,0 +1,87 @@
+import typing
+from dataclasses import dataclass
+from solders.pubkey import Pubkey
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+import borsh_construct as borsh
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.error import AccountInvalidDiscriminator
+from anchorpy.utils.rpc import get_multiple_accounts
+from anchorpy.borsh_extension import BorshPubkey
+from ..program_id import PROGRAM_ID
+
+
+class BaseAccountJSON(typing.TypedDict):
+ base_data: int
+ base_data_key: str
+
+
+@dataclass
+class BaseAccount:
+ discriminator: typing.ClassVar = b"\x10Z\x82\xf2\x9f\n\xe8\x85"
+ layout: typing.ClassVar = borsh.CStruct(
+ "base_data" / borsh.U64, "base_data_key" / BorshPubkey
+ )
+ base_data: int
+ base_data_key: Pubkey
+
+ @classmethod
+ async def fetch(
+ cls,
+ conn: AsyncClient,
+ address: Pubkey,
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.Optional["BaseAccount"]:
+ resp = await conn.get_account_info(address, commitment=commitment)
+ info = resp.value
+ if info is None:
+ return None
+ if info.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ bytes_data = info.data
+ return cls.decode(bytes_data)
+
+ @classmethod
+ async def fetch_multiple(
+ cls,
+ conn: AsyncClient,
+ addresses: list[Pubkey],
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.List[typing.Optional["BaseAccount"]]:
+ infos = await get_multiple_accounts(conn, addresses, commitment=commitment)
+ res: typing.List[typing.Optional["BaseAccount"]] = []
+ for info in infos:
+ if info is None:
+ res.append(None)
+ continue
+ if info.account.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ res.append(cls.decode(info.account.data))
+ return res
+
+ @classmethod
+ def decode(cls, data: bytes) -> "BaseAccount":
+ if data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator:
+ raise AccountInvalidDiscriminator(
+ "The discriminator for this account is invalid"
+ )
+ dec = BaseAccount.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])
+ return cls(
+ base_data=dec.base_data,
+ base_data_key=dec.base_data_key,
+ )
+
+ def to_json(self) -> BaseAccountJSON:
+ return {
+ "base_data": self.base_data,
+ "base_data_key": str(self.base_data_key),
+ }
+
+ @classmethod
+ def from_json(cls, obj: BaseAccountJSON) -> "BaseAccount":
+ return cls(
+ base_data=obj["base_data"],
+ base_data_key=Pubkey.from_string(obj["base_data_key"]),
+ )
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/my_account.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/my_account.py
new file mode 100644
index 0000000..49c922b
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/my_account.py
@@ -0,0 +1,79 @@
+import typing
+from dataclasses import dataclass
+from solders.pubkey import Pubkey
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+import borsh_construct as borsh
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.error import AccountInvalidDiscriminator
+from anchorpy.utils.rpc import get_multiple_accounts
+from ..program_id import PROGRAM_ID
+
+
+class MyAccountJSON(typing.TypedDict):
+ data: int
+
+
+@dataclass
+class MyAccount:
+ discriminator: typing.ClassVar = b"\xf6\x1c\x06W\xfb-2*"
+ layout: typing.ClassVar = borsh.CStruct("data" / borsh.U64)
+ data: int
+
+ @classmethod
+ async def fetch(
+ cls,
+ conn: AsyncClient,
+ address: Pubkey,
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.Optional["MyAccount"]:
+ resp = await conn.get_account_info(address, commitment=commitment)
+ info = resp.value
+ if info is None:
+ return None
+ if info.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ bytes_data = info.data
+ return cls.decode(bytes_data)
+
+ @classmethod
+ async def fetch_multiple(
+ cls,
+ conn: AsyncClient,
+ addresses: list[Pubkey],
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.List[typing.Optional["MyAccount"]]:
+ infos = await get_multiple_accounts(conn, addresses, commitment=commitment)
+ res: typing.List[typing.Optional["MyAccount"]] = []
+ for info in infos:
+ if info is None:
+ res.append(None)
+ continue
+ if info.account.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ res.append(cls.decode(info.account.data))
+ return res
+
+ @classmethod
+ def decode(cls, data: bytes) -> "MyAccount":
+ if data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator:
+ raise AccountInvalidDiscriminator(
+ "The discriminator for this account is invalid"
+ )
+ dec = MyAccount.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])
+ return cls(
+ data=dec.data,
+ )
+
+ def to_json(self) -> MyAccountJSON:
+ return {
+ "data": self.data,
+ }
+
+ @classmethod
+ def from_json(cls, obj: MyAccountJSON) -> "MyAccount":
+ return cls(
+ data=obj["data"],
+ )
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/state.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/state.py
new file mode 100644
index 0000000..1c0f39f
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/state.py
@@ -0,0 +1,259 @@
+import typing
+from dataclasses import dataclass
+from construct import Construct
+from solders.pubkey import Pubkey
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+import borsh_construct as borsh
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.error import AccountInvalidDiscriminator
+from anchorpy.utils.rpc import get_multiple_accounts
+from anchorpy.borsh_extension import BorshPubkey
+from ..program_id import PROGRAM_ID
+from .. import types
+
+
+class StateJSON(typing.TypedDict):
+ bool_field: bool
+ u8_field: int
+ i8_field: int
+ u16_field: int
+ i16_field: int
+ u32_field: int
+ i32_field: int
+ f32_field: float
+ u64_field: int
+ i64_field: int
+ f64_field: float
+ u128_field: int
+ i128_field: int
+ bytes_field: list[int]
+ string_field: str
+ pubkey_field: str
+ vec_field: list[int]
+ vec_struct_field: list[types.foo_struct.FooStructJSON]
+ option_field: typing.Optional[bool]
+ option_struct_field: typing.Optional[types.foo_struct.FooStructJSON]
+ struct_field: types.foo_struct.FooStructJSON
+ array_field: list[bool]
+ enum_field1: types.foo_enum.FooEnumJSON
+ enum_field2: types.foo_enum.FooEnumJSON
+ enum_field3: types.foo_enum.FooEnumJSON
+ enum_field4: types.foo_enum.FooEnumJSON
+
+
+@dataclass
+class State:
+ discriminator: typing.ClassVar = b"\xd8\x92k^hK\xb6\xb1"
+ layout: typing.ClassVar = borsh.CStruct(
+ "bool_field" / borsh.Bool,
+ "u8_field" / borsh.U8,
+ "i8_field" / borsh.I8,
+ "u16_field" / borsh.U16,
+ "i16_field" / borsh.I16,
+ "u32_field" / borsh.U32,
+ "i32_field" / borsh.I32,
+ "f32_field" / borsh.F32,
+ "u64_field" / borsh.U64,
+ "i64_field" / borsh.I64,
+ "f64_field" / borsh.F64,
+ "u128_field" / borsh.U128,
+ "i128_field" / borsh.I128,
+ "bytes_field" / borsh.Bytes,
+ "string_field" / borsh.String,
+ "pubkey_field" / BorshPubkey,
+ "vec_field" / borsh.Vec(typing.cast(Construct, borsh.U64)),
+ "vec_struct_field"
+ / borsh.Vec(typing.cast(Construct, types.foo_struct.FooStruct.layout)),
+ "option_field" / borsh.Option(borsh.Bool),
+ "option_struct_field" / borsh.Option(types.foo_struct.FooStruct.layout),
+ "struct_field" / types.foo_struct.FooStruct.layout,
+ "array_field" / borsh.Bool[3],
+ "enum_field1" / types.foo_enum.layout,
+ "enum_field2" / types.foo_enum.layout,
+ "enum_field3" / types.foo_enum.layout,
+ "enum_field4" / types.foo_enum.layout,
+ )
+ bool_field: bool
+ u8_field: int
+ i8_field: int
+ u16_field: int
+ i16_field: int
+ u32_field: int
+ i32_field: int
+ f32_field: float
+ u64_field: int
+ i64_field: int
+ f64_field: float
+ u128_field: int
+ i128_field: int
+ bytes_field: bytes
+ string_field: str
+ pubkey_field: Pubkey
+ vec_field: list[int]
+ vec_struct_field: list[types.foo_struct.FooStruct]
+ option_field: typing.Optional[bool]
+ option_struct_field: typing.Optional[types.foo_struct.FooStruct]
+ struct_field: types.foo_struct.FooStruct
+ array_field: list[bool]
+ enum_field1: types.foo_enum.FooEnumKind
+ enum_field2: types.foo_enum.FooEnumKind
+ enum_field3: types.foo_enum.FooEnumKind
+ enum_field4: types.foo_enum.FooEnumKind
+
+ @classmethod
+ async def fetch(
+ cls,
+ conn: AsyncClient,
+ address: Pubkey,
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.Optional["State"]:
+ resp = await conn.get_account_info(address, commitment=commitment)
+ info = resp.value
+ if info is None:
+ return None
+ if info.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ bytes_data = info.data
+ return cls.decode(bytes_data)
+
+ @classmethod
+ async def fetch_multiple(
+ cls,
+ conn: AsyncClient,
+ addresses: list[Pubkey],
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.List[typing.Optional["State"]]:
+ infos = await get_multiple_accounts(conn, addresses, commitment=commitment)
+ res: typing.List[typing.Optional["State"]] = []
+ for info in infos:
+ if info is None:
+ res.append(None)
+ continue
+ if info.account.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ res.append(cls.decode(info.account.data))
+ return res
+
+ @classmethod
+ def decode(cls, data: bytes) -> "State":
+ if data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator:
+ raise AccountInvalidDiscriminator(
+ "The discriminator for this account is invalid"
+ )
+ dec = State.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])
+ return cls(
+ bool_field=dec.bool_field,
+ u8_field=dec.u8_field,
+ i8_field=dec.i8_field,
+ u16_field=dec.u16_field,
+ i16_field=dec.i16_field,
+ u32_field=dec.u32_field,
+ i32_field=dec.i32_field,
+ f32_field=dec.f32_field,
+ u64_field=dec.u64_field,
+ i64_field=dec.i64_field,
+ f64_field=dec.f64_field,
+ u128_field=dec.u128_field,
+ i128_field=dec.i128_field,
+ bytes_field=dec.bytes_field,
+ string_field=dec.string_field,
+ pubkey_field=dec.pubkey_field,
+ vec_field=dec.vec_field,
+ vec_struct_field=list(
+ map(
+ lambda item: types.foo_struct.FooStruct.from_decoded(item),
+ dec.vec_struct_field,
+ )
+ ),
+ option_field=dec.option_field,
+ option_struct_field=(
+ None
+ if dec.option_struct_field is None
+ else types.foo_struct.FooStruct.from_decoded(dec.option_struct_field)
+ ),
+ struct_field=types.foo_struct.FooStruct.from_decoded(dec.struct_field),
+ array_field=dec.array_field,
+ enum_field1=types.foo_enum.from_decoded(dec.enum_field1),
+ enum_field2=types.foo_enum.from_decoded(dec.enum_field2),
+ enum_field3=types.foo_enum.from_decoded(dec.enum_field3),
+ enum_field4=types.foo_enum.from_decoded(dec.enum_field4),
+ )
+
+ def to_json(self) -> StateJSON:
+ return {
+ "bool_field": self.bool_field,
+ "u8_field": self.u8_field,
+ "i8_field": self.i8_field,
+ "u16_field": self.u16_field,
+ "i16_field": self.i16_field,
+ "u32_field": self.u32_field,
+ "i32_field": self.i32_field,
+ "f32_field": self.f32_field,
+ "u64_field": self.u64_field,
+ "i64_field": self.i64_field,
+ "f64_field": self.f64_field,
+ "u128_field": self.u128_field,
+ "i128_field": self.i128_field,
+ "bytes_field": list(self.bytes_field),
+ "string_field": self.string_field,
+ "pubkey_field": str(self.pubkey_field),
+ "vec_field": self.vec_field,
+ "vec_struct_field": list(
+ map(lambda item: item.to_json(), self.vec_struct_field)
+ ),
+ "option_field": self.option_field,
+ "option_struct_field": (
+ None
+ if self.option_struct_field is None
+ else self.option_struct_field.to_json()
+ ),
+ "struct_field": self.struct_field.to_json(),
+ "array_field": self.array_field,
+ "enum_field1": self.enum_field1.to_json(),
+ "enum_field2": self.enum_field2.to_json(),
+ "enum_field3": self.enum_field3.to_json(),
+ "enum_field4": self.enum_field4.to_json(),
+ }
+
+ @classmethod
+ def from_json(cls, obj: StateJSON) -> "State":
+ return cls(
+ bool_field=obj["bool_field"],
+ u8_field=obj["u8_field"],
+ i8_field=obj["i8_field"],
+ u16_field=obj["u16_field"],
+ i16_field=obj["i16_field"],
+ u32_field=obj["u32_field"],
+ i32_field=obj["i32_field"],
+ f32_field=obj["f32_field"],
+ u64_field=obj["u64_field"],
+ i64_field=obj["i64_field"],
+ f64_field=obj["f64_field"],
+ u128_field=obj["u128_field"],
+ i128_field=obj["i128_field"],
+ bytes_field=bytes(obj["bytes_field"]),
+ string_field=obj["string_field"],
+ pubkey_field=Pubkey.from_string(obj["pubkey_field"]),
+ vec_field=obj["vec_field"],
+ vec_struct_field=list(
+ map(
+ lambda item: types.foo_struct.FooStruct.from_json(item),
+ obj["vec_struct_field"],
+ )
+ ),
+ option_field=obj["option_field"],
+ option_struct_field=(
+ None
+ if obj["option_struct_field"] is None
+ else types.foo_struct.FooStruct.from_json(obj["option_struct_field"])
+ ),
+ struct_field=types.foo_struct.FooStruct.from_json(obj["struct_field"]),
+ array_field=obj["array_field"],
+ enum_field1=types.foo_enum.from_json(obj["enum_field1"]),
+ enum_field2=types.foo_enum.from_json(obj["enum_field2"]),
+ enum_field3=types.foo_enum.from_json(obj["enum_field3"]),
+ enum_field4=types.foo_enum.from_json(obj["enum_field4"]),
+ )
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/state2.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/state2.py
new file mode 100644
index 0000000..2dd9ab1
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/accounts/state2.py
@@ -0,0 +1,82 @@
+import typing
+from dataclasses import dataclass
+from construct import Construct
+from solders.pubkey import Pubkey
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+import borsh_construct as borsh
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.error import AccountInvalidDiscriminator
+from anchorpy.utils.rpc import get_multiple_accounts
+from ..program_id import PROGRAM_ID
+
+
+class State2JSON(typing.TypedDict):
+ vec_of_option: list[typing.Optional[int]]
+
+
+@dataclass
+class State2:
+ discriminator: typing.ClassVar = b"ja\xff\xa1\xfa\xcd\xb9\xc0"
+ layout: typing.ClassVar = borsh.CStruct(
+ "vec_of_option" / borsh.Vec(typing.cast(Construct, borsh.Option(borsh.U64)))
+ )
+ vec_of_option: list[typing.Optional[int]]
+
+ @classmethod
+ async def fetch(
+ cls,
+ conn: AsyncClient,
+ address: Pubkey,
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.Optional["State2"]:
+ resp = await conn.get_account_info(address, commitment=commitment)
+ info = resp.value
+ if info is None:
+ return None
+ if info.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ bytes_data = info.data
+ return cls.decode(bytes_data)
+
+ @classmethod
+ async def fetch_multiple(
+ cls,
+ conn: AsyncClient,
+ addresses: list[Pubkey],
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.List[typing.Optional["State2"]]:
+ infos = await get_multiple_accounts(conn, addresses, commitment=commitment)
+ res: typing.List[typing.Optional["State2"]] = []
+ for info in infos:
+ if info is None:
+ res.append(None)
+ continue
+ if info.account.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ res.append(cls.decode(info.account.data))
+ return res
+
+ @classmethod
+ def decode(cls, data: bytes) -> "State2":
+ if data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator:
+ raise AccountInvalidDiscriminator(
+ "The discriminator for this account is invalid"
+ )
+ dec = State2.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])
+ return cls(
+ vec_of_option=dec.vec_of_option,
+ )
+
+ def to_json(self) -> State2JSON:
+ return {
+ "vec_of_option": self.vec_of_option,
+ }
+
+ @classmethod
+ def from_json(cls, obj: State2JSON) -> "State2":
+ return cls(
+ vec_of_option=obj["vec_of_option"],
+ )
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/errors/__init__.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/errors/__init__.py
new file mode 100644
index 0000000..421993d
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/errors/__init__.py
@@ -0,0 +1,29 @@
+import typing
+import re
+from solders.transaction_status import (
+ InstructionErrorCustom,
+ TransactionErrorInstructionError,
+)
+from solana.rpc.core import RPCException
+from solders.rpc.errors import SendTransactionPreflightFailureMessage
+from anchorpy.error import extract_code_and_logs
+from ..program_id import PROGRAM_ID
+from . import anchor
+from . import custom
+
+
+def from_code(code: int) -> typing.Union[custom.CustomError, anchor.AnchorError, None]:
+ return custom.from_code(code) if code >= 6000 else anchor.from_code(code)
+
+
+error_re = re.compile(r"Program (\w+) failed: custom program error: (\w+)")
+
+
+def from_tx_error(
+ error: RPCException,
+) -> typing.Union[anchor.AnchorError, custom.CustomError, None]:
+ err_info = error.args[0]
+ extracted = extract_code_and_logs(err_info, PROGRAM_ID)
+ if extracted is None:
+ return None
+ return from_code(extracted[0])
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/errors/anchor.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/errors/anchor.py
new file mode 100644
index 0000000..3f266ef
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/errors/anchor.py
@@ -0,0 +1,590 @@
+import typing
+from anchorpy.error import ProgramError
+
+
+class InstructionMissing(ProgramError):
+ def __init__(self):
+ super().__init__(100, "8 byte instruction identifier not provided")
+
+ code = 100
+ name = "InstructionMissing"
+ msg = "8 byte instruction identifier not provided"
+
+
+class InstructionFallbackNotFound(ProgramError):
+ def __init__(self):
+ super().__init__(101, "Fallback functions are not supported")
+
+ code = 101
+ name = "InstructionFallbackNotFound"
+ msg = "Fallback functions are not supported"
+
+
+class InstructionDidNotDeserialize(ProgramError):
+ def __init__(self):
+ super().__init__(102, "The program could not deserialize the given instruction")
+
+ code = 102
+ name = "InstructionDidNotDeserialize"
+ msg = "The program could not deserialize the given instruction"
+
+
+class InstructionDidNotSerialize(ProgramError):
+ def __init__(self):
+ super().__init__(103, "The program could not serialize the given instruction")
+
+ code = 103
+ name = "InstructionDidNotSerialize"
+ msg = "The program could not serialize the given instruction"
+
+
+class IdlInstructionStub(ProgramError):
+ def __init__(self):
+ super().__init__(1000, "The program was compiled without idl instructions")
+
+ code = 1000
+ name = "IdlInstructionStub"
+ msg = "The program was compiled without idl instructions"
+
+
+class IdlInstructionInvalidProgram(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 1001, "The transaction was given an invalid program for the IDL instruction"
+ )
+
+ code = 1001
+ name = "IdlInstructionInvalidProgram"
+ msg = "The transaction was given an invalid program for the IDL instruction"
+
+
+class ConstraintMut(ProgramError):
+ def __init__(self):
+ super().__init__(2000, "A mut constraint was violated")
+
+ code = 2000
+ name = "ConstraintMut"
+ msg = "A mut constraint was violated"
+
+
+class ConstraintHasOne(ProgramError):
+ def __init__(self):
+ super().__init__(2001, "A has_one constraint was violated")
+
+ code = 2001
+ name = "ConstraintHasOne"
+ msg = "A has_one constraint was violated"
+
+
+class ConstraintSigner(ProgramError):
+ def __init__(self):
+ super().__init__(2002, "A signer constraint was violated")
+
+ code = 2002
+ name = "ConstraintSigner"
+ msg = "A signer constraint was violated"
+
+
+class ConstraintRaw(ProgramError):
+ def __init__(self):
+ super().__init__(2003, "A raw constraint was violated")
+
+ code = 2003
+ name = "ConstraintRaw"
+ msg = "A raw constraint was violated"
+
+
+class ConstraintOwner(ProgramError):
+ def __init__(self):
+ super().__init__(2004, "An owner constraint was violated")
+
+ code = 2004
+ name = "ConstraintOwner"
+ msg = "An owner constraint was violated"
+
+
+class ConstraintRentExempt(ProgramError):
+ def __init__(self):
+ super().__init__(2005, "A rent exempt constraint was violated")
+
+ code = 2005
+ name = "ConstraintRentExempt"
+ msg = "A rent exempt constraint was violated"
+
+
+class ConstraintSeeds(ProgramError):
+ def __init__(self):
+ super().__init__(2006, "A seeds constraint was violated")
+
+ code = 2006
+ name = "ConstraintSeeds"
+ msg = "A seeds constraint was violated"
+
+
+class ConstraintExecutable(ProgramError):
+ def __init__(self):
+ super().__init__(2007, "An executable constraint was violated")
+
+ code = 2007
+ name = "ConstraintExecutable"
+ msg = "An executable constraint was violated"
+
+
+class ConstraintState(ProgramError):
+ def __init__(self):
+ super().__init__(2008, "A state constraint was violated")
+
+ code = 2008
+ name = "ConstraintState"
+ msg = "A state constraint was violated"
+
+
+class ConstraintAssociated(ProgramError):
+ def __init__(self):
+ super().__init__(2009, "An associated constraint was violated")
+
+ code = 2009
+ name = "ConstraintAssociated"
+ msg = "An associated constraint was violated"
+
+
+class ConstraintAssociatedInit(ProgramError):
+ def __init__(self):
+ super().__init__(2010, "An associated init constraint was violated")
+
+ code = 2010
+ name = "ConstraintAssociatedInit"
+ msg = "An associated init constraint was violated"
+
+
+class ConstraintClose(ProgramError):
+ def __init__(self):
+ super().__init__(2011, "A close constraint was violated")
+
+ code = 2011
+ name = "ConstraintClose"
+ msg = "A close constraint was violated"
+
+
+class ConstraintAddress(ProgramError):
+ def __init__(self):
+ super().__init__(2012, "An address constraint was violated")
+
+ code = 2012
+ name = "ConstraintAddress"
+ msg = "An address constraint was violated"
+
+
+class ConstraintZero(ProgramError):
+ def __init__(self):
+ super().__init__(2013, "Expected zero account discriminant")
+
+ code = 2013
+ name = "ConstraintZero"
+ msg = "Expected zero account discriminant"
+
+
+class ConstraintTokenMint(ProgramError):
+ def __init__(self):
+ super().__init__(2014, "A token mint constraint was violated")
+
+ code = 2014
+ name = "ConstraintTokenMint"
+ msg = "A token mint constraint was violated"
+
+
+class ConstraintTokenOwner(ProgramError):
+ def __init__(self):
+ super().__init__(2015, "A token owner constraint was violated")
+
+ code = 2015
+ name = "ConstraintTokenOwner"
+ msg = "A token owner constraint was violated"
+
+
+class ConstraintMintMintAuthority(ProgramError):
+ def __init__(self):
+ super().__init__(2016, "A mint mint authority constraint was violated")
+
+ code = 2016
+ name = "ConstraintMintMintAuthority"
+ msg = "A mint mint authority constraint was violated"
+
+
+class ConstraintMintFreezeAuthority(ProgramError):
+ def __init__(self):
+ super().__init__(2017, "A mint freeze authority constraint was violated")
+
+ code = 2017
+ name = "ConstraintMintFreezeAuthority"
+ msg = "A mint freeze authority constraint was violated"
+
+
+class ConstraintMintDecimals(ProgramError):
+ def __init__(self):
+ super().__init__(2018, "A mint decimals constraint was violated")
+
+ code = 2018
+ name = "ConstraintMintDecimals"
+ msg = "A mint decimals constraint was violated"
+
+
+class ConstraintSpace(ProgramError):
+ def __init__(self):
+ super().__init__(2019, "A space constraint was violated")
+
+ code = 2019
+ name = "ConstraintSpace"
+ msg = "A space constraint was violated"
+
+
+class RequireViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2500, "A require expression was violated")
+
+ code = 2500
+ name = "RequireViolated"
+ msg = "A require expression was violated"
+
+
+class RequireEqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2501, "A require_eq expression was violated")
+
+ code = 2501
+ name = "RequireEqViolated"
+ msg = "A require_eq expression was violated"
+
+
+class RequireKeysEqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2502, "A require_keys_eq expression was violated")
+
+ code = 2502
+ name = "RequireKeysEqViolated"
+ msg = "A require_keys_eq expression was violated"
+
+
+class RequireNeqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2503, "A require_neq expression was violated")
+
+ code = 2503
+ name = "RequireNeqViolated"
+ msg = "A require_neq expression was violated"
+
+
+class RequireKeysNeqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2504, "A require_keys_neq expression was violated")
+
+ code = 2504
+ name = "RequireKeysNeqViolated"
+ msg = "A require_keys_neq expression was violated"
+
+
+class RequireGtViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2505, "A require_gt expression was violated")
+
+ code = 2505
+ name = "RequireGtViolated"
+ msg = "A require_gt expression was violated"
+
+
+class RequireGteViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2506, "A require_gte expression was violated")
+
+ code = 2506
+ name = "RequireGteViolated"
+ msg = "A require_gte expression was violated"
+
+
+class AccountDiscriminatorAlreadySet(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3000, "The account discriminator was already set on this account"
+ )
+
+ code = 3000
+ name = "AccountDiscriminatorAlreadySet"
+ msg = "The account discriminator was already set on this account"
+
+
+class AccountDiscriminatorNotFound(ProgramError):
+ def __init__(self):
+ super().__init__(3001, "No 8 byte discriminator was found on the account")
+
+ code = 3001
+ name = "AccountDiscriminatorNotFound"
+ msg = "No 8 byte discriminator was found on the account"
+
+
+class AccountDiscriminatorMismatch(ProgramError):
+ def __init__(self):
+ super().__init__(3002, "8 byte discriminator did not match what was expected")
+
+ code = 3002
+ name = "AccountDiscriminatorMismatch"
+ msg = "8 byte discriminator did not match what was expected"
+
+
+class AccountDidNotDeserialize(ProgramError):
+ def __init__(self):
+ super().__init__(3003, "Failed to deserialize the account")
+
+ code = 3003
+ name = "AccountDidNotDeserialize"
+ msg = "Failed to deserialize the account"
+
+
+class AccountDidNotSerialize(ProgramError):
+ def __init__(self):
+ super().__init__(3004, "Failed to serialize the account")
+
+ code = 3004
+ name = "AccountDidNotSerialize"
+ msg = "Failed to serialize the account"
+
+
+class AccountNotEnoughKeys(ProgramError):
+ def __init__(self):
+ super().__init__(3005, "Not enough account keys given to the instruction")
+
+ code = 3005
+ name = "AccountNotEnoughKeys"
+ msg = "Not enough account keys given to the instruction"
+
+
+class AccountNotMutable(ProgramError):
+ def __init__(self):
+ super().__init__(3006, "The given account is not mutable")
+
+ code = 3006
+ name = "AccountNotMutable"
+ msg = "The given account is not mutable"
+
+
+class AccountOwnedByWrongProgram(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3007, "The given account is owned by a different program than expected"
+ )
+
+ code = 3007
+ name = "AccountOwnedByWrongProgram"
+ msg = "The given account is owned by a different program than expected"
+
+
+class InvalidProgramId(ProgramError):
+ def __init__(self):
+ super().__init__(3008, "Program ID was not as expected")
+
+ code = 3008
+ name = "InvalidProgramId"
+ msg = "Program ID was not as expected"
+
+
+class InvalidProgramExecutable(ProgramError):
+ def __init__(self):
+ super().__init__(3009, "Program account is not executable")
+
+ code = 3009
+ name = "InvalidProgramExecutable"
+ msg = "Program account is not executable"
+
+
+class AccountNotSigner(ProgramError):
+ def __init__(self):
+ super().__init__(3010, "The given account did not sign")
+
+ code = 3010
+ name = "AccountNotSigner"
+ msg = "The given account did not sign"
+
+
+class AccountNotSystemOwned(ProgramError):
+ def __init__(self):
+ super().__init__(3011, "The given account is not owned by the system program")
+
+ code = 3011
+ name = "AccountNotSystemOwned"
+ msg = "The given account is not owned by the system program"
+
+
+class AccountNotInitialized(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3012, "The program expected this account to be already initialized"
+ )
+
+ code = 3012
+ name = "AccountNotInitialized"
+ msg = "The program expected this account to be already initialized"
+
+
+class AccountNotProgramData(ProgramError):
+ def __init__(self):
+ super().__init__(3013, "The given account is not a program data account")
+
+ code = 3013
+ name = "AccountNotProgramData"
+ msg = "The given account is not a program data account"
+
+
+class AccountNotAssociatedTokenAccount(ProgramError):
+ def __init__(self):
+ super().__init__(3014, "The given account is not the associated token account")
+
+ code = 3014
+ name = "AccountNotAssociatedTokenAccount"
+ msg = "The given account is not the associated token account"
+
+
+class AccountSysvarMismatch(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3015, "The given public key does not match the required sysvar"
+ )
+
+ code = 3015
+ name = "AccountSysvarMismatch"
+ msg = "The given public key does not match the required sysvar"
+
+
+class StateInvalidAddress(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 4000, "The given state account does not have the correct address"
+ )
+
+ code = 4000
+ name = "StateInvalidAddress"
+ msg = "The given state account does not have the correct address"
+
+
+class Deprecated(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 5000, "The API being used is deprecated and should no longer be used"
+ )
+
+ code = 5000
+ name = "Deprecated"
+ msg = "The API being used is deprecated and should no longer be used"
+
+
+AnchorError = typing.Union[
+ InstructionMissing,
+ InstructionFallbackNotFound,
+ InstructionDidNotDeserialize,
+ InstructionDidNotSerialize,
+ IdlInstructionStub,
+ IdlInstructionInvalidProgram,
+ ConstraintMut,
+ ConstraintHasOne,
+ ConstraintSigner,
+ ConstraintRaw,
+ ConstraintOwner,
+ ConstraintRentExempt,
+ ConstraintSeeds,
+ ConstraintExecutable,
+ ConstraintState,
+ ConstraintAssociated,
+ ConstraintAssociatedInit,
+ ConstraintClose,
+ ConstraintAddress,
+ ConstraintZero,
+ ConstraintTokenMint,
+ ConstraintTokenOwner,
+ ConstraintMintMintAuthority,
+ ConstraintMintFreezeAuthority,
+ ConstraintMintDecimals,
+ ConstraintSpace,
+ RequireViolated,
+ RequireEqViolated,
+ RequireKeysEqViolated,
+ RequireNeqViolated,
+ RequireKeysNeqViolated,
+ RequireGtViolated,
+ RequireGteViolated,
+ AccountDiscriminatorAlreadySet,
+ AccountDiscriminatorNotFound,
+ AccountDiscriminatorMismatch,
+ AccountDidNotDeserialize,
+ AccountDidNotSerialize,
+ AccountNotEnoughKeys,
+ AccountNotMutable,
+ AccountOwnedByWrongProgram,
+ InvalidProgramId,
+ InvalidProgramExecutable,
+ AccountNotSigner,
+ AccountNotSystemOwned,
+ AccountNotInitialized,
+ AccountNotProgramData,
+ AccountNotAssociatedTokenAccount,
+ AccountSysvarMismatch,
+ StateInvalidAddress,
+ Deprecated,
+]
+ANCHOR_ERROR_MAP: dict[int, AnchorError] = {
+ 100: InstructionMissing(),
+ 101: InstructionFallbackNotFound(),
+ 102: InstructionDidNotDeserialize(),
+ 103: InstructionDidNotSerialize(),
+ 1000: IdlInstructionStub(),
+ 1001: IdlInstructionInvalidProgram(),
+ 2000: ConstraintMut(),
+ 2001: ConstraintHasOne(),
+ 2002: ConstraintSigner(),
+ 2003: ConstraintRaw(),
+ 2004: ConstraintOwner(),
+ 2005: ConstraintRentExempt(),
+ 2006: ConstraintSeeds(),
+ 2007: ConstraintExecutable(),
+ 2008: ConstraintState(),
+ 2009: ConstraintAssociated(),
+ 2010: ConstraintAssociatedInit(),
+ 2011: ConstraintClose(),
+ 2012: ConstraintAddress(),
+ 2013: ConstraintZero(),
+ 2014: ConstraintTokenMint(),
+ 2015: ConstraintTokenOwner(),
+ 2016: ConstraintMintMintAuthority(),
+ 2017: ConstraintMintFreezeAuthority(),
+ 2018: ConstraintMintDecimals(),
+ 2019: ConstraintSpace(),
+ 2500: RequireViolated(),
+ 2501: RequireEqViolated(),
+ 2502: RequireKeysEqViolated(),
+ 2503: RequireNeqViolated(),
+ 2504: RequireKeysNeqViolated(),
+ 2505: RequireGtViolated(),
+ 2506: RequireGteViolated(),
+ 3000: AccountDiscriminatorAlreadySet(),
+ 3001: AccountDiscriminatorNotFound(),
+ 3002: AccountDiscriminatorMismatch(),
+ 3003: AccountDidNotDeserialize(),
+ 3004: AccountDidNotSerialize(),
+ 3005: AccountNotEnoughKeys(),
+ 3006: AccountNotMutable(),
+ 3007: AccountOwnedByWrongProgram(),
+ 3008: InvalidProgramId(),
+ 3009: InvalidProgramExecutable(),
+ 3010: AccountNotSigner(),
+ 3011: AccountNotSystemOwned(),
+ 3012: AccountNotInitialized(),
+ 3013: AccountNotProgramData(),
+ 3014: AccountNotAssociatedTokenAccount(),
+ 3015: AccountSysvarMismatch(),
+ 4000: StateInvalidAddress(),
+ 5000: Deprecated(),
+}
+
+
+def from_code(code: int) -> typing.Optional[AnchorError]:
+ maybe_err = ANCHOR_ERROR_MAP.get(code)
+ if maybe_err is None:
+ return None
+ return maybe_err
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/errors/custom.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/errors/custom.py
new file mode 100644
index 0000000..f92f321
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/errors/custom.py
@@ -0,0 +1,34 @@
+import typing
+from anchorpy.error import ProgramError
+
+
+class SomeError(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(6000, "Example error.")
+
+ code = 6000
+ name = "SomeError"
+ msg = "Example error."
+
+
+class OtherError(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(6001, "Another error.")
+
+ code = 6001
+ name = "OtherError"
+ msg = "Another error."
+
+
+CustomError = typing.Union[SomeError, OtherError]
+CUSTOM_ERROR_MAP: dict[int, CustomError] = {
+ 6000: SomeError(),
+ 6001: OtherError(),
+}
+
+
+def from_code(code: int) -> typing.Optional[CustomError]:
+ maybe_err = CUSTOM_ERROR_MAP.get(code)
+ if maybe_err is None:
+ return None
+ return maybe_err
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/__init__.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/__init__.py
new file mode 100644
index 0000000..dee442f
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/__init__.py
@@ -0,0 +1,17 @@
+from .initialize import initialize, InitializeAccounts
+from .initialize_with_values import (
+ initialize_with_values,
+ InitializeWithValuesArgs,
+ InitializeWithValuesAccounts,
+)
+from .initialize_with_values2 import (
+ initialize_with_values2,
+ InitializeWithValues2Args,
+ InitializeWithValues2Accounts,
+)
+from .cause_error import cause_error
+from .init_my_account import init_my_account, InitMyAccountArgs, InitMyAccountAccounts
+from .increment_state_when_present import (
+ increment_state_when_present,
+ IncrementStateWhenPresentAccounts,
+)
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/cause_error.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/cause_error.py
new file mode 100644
index 0000000..4bbd6f3
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/cause_error.py
@@ -0,0 +1,18 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+def cause_error(
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = []
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"Ch%\x11\x02\x9bD\x11"
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/increment_state_when_present.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/increment_state_when_present.py
new file mode 100644
index 0000000..f7a41af
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/increment_state_when_present.py
@@ -0,0 +1,33 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class IncrementStateWhenPresentAccounts(typing.TypedDict):
+ first_state: typing.Optional[Pubkey]
+ second_state: Pubkey
+
+
+def increment_state_when_present(
+ accounts: IncrementStateWhenPresentAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["first_state"], is_signer=False, is_writable=True)
+ if accounts["first_state"]
+ else AccountMeta(pubkey=program_id, is_signer=False, is_writable=False),
+ AccountMeta(
+ pubkey=accounts["second_state"], is_signer=False, is_writable=False
+ ),
+ AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xf1!\xdd(\xa3Jy%"
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/init_my_account.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/init_my_account.py
new file mode 100644
index 0000000..063a597
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/init_my_account.py
@@ -0,0 +1,72 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class InitMyAccountArgs(typing.TypedDict):
+ seed_a: int
+
+
+layout = borsh.CStruct("seed_a" / borsh.U8)
+NESTED_NESTED_ACCOUNT_NESTED = Pubkey.find_program_address(
+ seeds=[
+ b"nested-seed",
+ b"test",
+ b"hi",
+ b"hi",
+ b"\x01",
+ b"\x02\x00\x00\x00",
+ b"\x03\x00\x00\x00\x00\x00\x00\x00",
+ ],
+ program_id=PROGRAM_ID,
+)[0]
+INIT_MY_ACCOUNT_ACCOUNTS_ACCOUNT = Pubkey.find_program_address(
+ seeds=[
+ b"another-seed",
+ b"test",
+ b"hi",
+ b"hi",
+ b"\x01",
+ b"\x02\x00\x00\x00",
+ b"\x03\x00\x00\x00\x00\x00\x00\x00",
+ ],
+ program_id=PROGRAM_ID,
+)[0]
+
+
+class InitMyAccountAccounts(typing.TypedDict):
+ base: Pubkey
+ base2: Pubkey
+
+
+def init_my_account(
+ args: InitMyAccountArgs,
+ accounts: InitMyAccountAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["base"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["base2"], is_signer=False, is_writable=False),
+ AccountMeta(
+ pubkey=INIT_MY_ACCOUNT_ACCOUNTS_ACCOUNT, is_signer=False, is_writable=False
+ ),
+ AccountMeta(
+ pubkey=NESTED_NESTED_ACCOUNT_NESTED, is_signer=False, is_writable=False
+ ),
+ AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b" ;\x05\xcd^E\xe3z"
+ encoded_args = layout.build(
+ {
+ "seed_a": args["seed_a"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/initialize.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/initialize.py
new file mode 100644
index 0000000..45b0cb7
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/initialize.py
@@ -0,0 +1,32 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.sysvar import RENT, CLOCK
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class InitializeAccounts(typing.TypedDict):
+ state: Pubkey
+ payer: Pubkey
+
+
+def initialize(
+ accounts: InitializeAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["state"], is_signer=True, is_writable=True),
+ AccountMeta(pubkey=CLOCK, is_signer=False, is_writable=False),
+ AccountMeta(pubkey=RENT, is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["payer"], is_signer=True, is_writable=True),
+ AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xaf\xafm\x1f\r\x98\x9b\xed"
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/initialize_with_values.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/initialize_with_values.py
new file mode 100644
index 0000000..ccec19f
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/initialize_with_values.py
@@ -0,0 +1,132 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.sysvar import RENT, CLOCK
+from solders.instruction import Instruction, AccountMeta
+from anchorpy.borsh_extension import BorshPubkey
+from construct import Construct
+import borsh_construct as borsh
+from .. import types
+from ..program_id import PROGRAM_ID
+
+
+class InitializeWithValuesArgs(typing.TypedDict):
+ bool_field: bool
+ u8_field: int
+ i8_field: int
+ u16_field: int
+ i16_field: int
+ u32_field: int
+ i32_field: int
+ f32_field: float
+ u64_field: int
+ i64_field: int
+ f64_field: float
+ u128_field: int
+ i128_field: int
+ bytes_field: bytes
+ string_field: str
+ pubkey_field: Pubkey
+ vec_field: list[int]
+ vec_struct_field: list[types.foo_struct.FooStruct]
+ option_field: typing.Optional[bool]
+ option_struct_field: typing.Optional[types.foo_struct.FooStruct]
+ struct_field: types.foo_struct.FooStruct
+ array_field: list[bool]
+ enum_field1: types.foo_enum.FooEnumKind
+ enum_field2: types.foo_enum.FooEnumKind
+ enum_field3: types.foo_enum.FooEnumKind
+ enum_field4: types.foo_enum.FooEnumKind
+
+
+layout = borsh.CStruct(
+ "bool_field" / borsh.Bool,
+ "u8_field" / borsh.U8,
+ "i8_field" / borsh.I8,
+ "u16_field" / borsh.U16,
+ "i16_field" / borsh.I16,
+ "u32_field" / borsh.U32,
+ "i32_field" / borsh.I32,
+ "f32_field" / borsh.F32,
+ "u64_field" / borsh.U64,
+ "i64_field" / borsh.I64,
+ "f64_field" / borsh.F64,
+ "u128_field" / borsh.U128,
+ "i128_field" / borsh.I128,
+ "bytes_field" / borsh.Bytes,
+ "string_field" / borsh.String,
+ "pubkey_field" / BorshPubkey,
+ "vec_field" / borsh.Vec(typing.cast(Construct, borsh.U64)),
+ "vec_struct_field"
+ / borsh.Vec(typing.cast(Construct, types.foo_struct.FooStruct.layout)),
+ "option_field" / borsh.Option(borsh.Bool),
+ "option_struct_field" / borsh.Option(types.foo_struct.FooStruct.layout),
+ "struct_field" / types.foo_struct.FooStruct.layout,
+ "array_field" / borsh.Bool[3],
+ "enum_field1" / types.foo_enum.layout,
+ "enum_field2" / types.foo_enum.layout,
+ "enum_field3" / types.foo_enum.layout,
+ "enum_field4" / types.foo_enum.layout,
+)
+
+
+class InitializeWithValuesAccounts(typing.TypedDict):
+ state: Pubkey
+ payer: Pubkey
+
+
+def initialize_with_values(
+ args: InitializeWithValuesArgs,
+ accounts: InitializeWithValuesAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["state"], is_signer=True, is_writable=True),
+ AccountMeta(pubkey=CLOCK, is_signer=False, is_writable=False),
+ AccountMeta(pubkey=RENT, is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["payer"], is_signer=True, is_writable=True),
+ AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xdcI\x08\xd5\xb2E\xb5\x8d"
+ encoded_args = layout.build(
+ {
+ "bool_field": args["bool_field"],
+ "u8_field": args["u8_field"],
+ "i8_field": args["i8_field"],
+ "u16_field": args["u16_field"],
+ "i16_field": args["i16_field"],
+ "u32_field": args["u32_field"],
+ "i32_field": args["i32_field"],
+ "f32_field": args["f32_field"],
+ "u64_field": args["u64_field"],
+ "i64_field": args["i64_field"],
+ "f64_field": args["f64_field"],
+ "u128_field": args["u128_field"],
+ "i128_field": args["i128_field"],
+ "bytes_field": args["bytes_field"],
+ "string_field": args["string_field"],
+ "pubkey_field": args["pubkey_field"],
+ "vec_field": args["vec_field"],
+ "vec_struct_field": list(
+ map(lambda item: item.to_encodable(), args["vec_struct_field"])
+ ),
+ "option_field": args["option_field"],
+ "option_struct_field": (
+ None
+ if args["option_struct_field"] is None
+ else args["option_struct_field"].to_encodable()
+ ),
+ "struct_field": args["struct_field"].to_encodable(),
+ "array_field": args["array_field"],
+ "enum_field1": args["enum_field1"].to_encodable(),
+ "enum_field2": args["enum_field2"].to_encodable(),
+ "enum_field3": args["enum_field3"].to_encodable(),
+ "enum_field4": args["enum_field4"].to_encodable(),
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/initialize_with_values2.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/initialize_with_values2.py
new file mode 100644
index 0000000..6e56be8
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/instructions/initialize_with_values2.py
@@ -0,0 +1,45 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.instruction import Instruction, AccountMeta
+from construct import Construct
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class InitializeWithValues2Args(typing.TypedDict):
+ vec_of_option: list[typing.Optional[int]]
+
+
+layout = borsh.CStruct(
+ "vec_of_option" / borsh.Vec(typing.cast(Construct, borsh.Option(borsh.U64)))
+)
+
+
+class InitializeWithValues2Accounts(typing.TypedDict):
+ state: Pubkey
+ payer: Pubkey
+
+
+def initialize_with_values2(
+ args: InitializeWithValues2Args,
+ accounts: InitializeWithValues2Accounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["state"], is_signer=True, is_writable=True),
+ AccountMeta(pubkey=accounts["payer"], is_signer=True, is_writable=True),
+ AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xf8\xbe\x15a\xef\x94'\xb5"
+ encoded_args = layout.build(
+ {
+ "vec_of_option": args["vec_of_option"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/program_id.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/program_id.py
new file mode 100644
index 0000000..649b93e
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/program_id.py
@@ -0,0 +1,3 @@
+from solders.pubkey import Pubkey
+
+PROGRAM_ID = Pubkey.from_string("3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8")
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/types/__init__.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/types/__init__.py
new file mode 100644
index 0000000..a843328
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/types/__init__.py
@@ -0,0 +1,7 @@
+import typing
+from . import bar_struct
+from .bar_struct import BarStruct, BarStructJSON
+from . import foo_struct
+from .foo_struct import FooStruct, FooStructJSON
+from . import foo_enum
+from .foo_enum import FooEnumKind, FooEnumJSON
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/types/bar_struct.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/types/bar_struct.py
new file mode 100644
index 0000000..9ab95a7
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/types/bar_struct.py
@@ -0,0 +1,33 @@
+from __future__ import annotations
+import typing
+from dataclasses import dataclass
+from construct import Container
+import borsh_construct as borsh
+
+
+class BarStructJSON(typing.TypedDict):
+ some_field: bool
+ other_field: int
+
+
+@dataclass
+class BarStruct:
+ layout: typing.ClassVar = borsh.CStruct(
+ "some_field" / borsh.Bool, "other_field" / borsh.U8
+ )
+ some_field: bool
+ other_field: int
+
+ @classmethod
+ def from_decoded(cls, obj: Container) -> "BarStruct":
+ return cls(some_field=obj.some_field, other_field=obj.other_field)
+
+ def to_encodable(self) -> dict[str, typing.Any]:
+ return {"some_field": self.some_field, "other_field": self.other_field}
+
+ def to_json(self) -> BarStructJSON:
+ return {"some_field": self.some_field, "other_field": self.other_field}
+
+ @classmethod
+ def from_json(cls, obj: BarStructJSON) -> "BarStruct":
+ return cls(some_field=obj["some_field"], other_field=obj["other_field"])
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/types/foo_enum.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/types/foo_enum.py
new file mode 100644
index 0000000..b56185f
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/types/foo_enum.py
@@ -0,0 +1,370 @@
+from __future__ import annotations
+from . import bar_struct
+import typing
+from dataclasses import dataclass
+from construct import Construct
+from anchorpy.borsh_extension import EnumForCodegen
+import borsh_construct as borsh
+
+UnnamedJSONValue = tuple[bool, int, bar_struct.BarStructJSON]
+UnnamedSingleJSONValue = tuple[bar_struct.BarStructJSON]
+
+
+class NamedJSONValue(typing.TypedDict):
+ bool_field: bool
+ u8_field: int
+ nested: bar_struct.BarStructJSON
+
+
+StructJSONValue = tuple[bar_struct.BarStructJSON]
+OptionStructJSONValue = tuple[typing.Optional[bar_struct.BarStructJSON]]
+VecStructJSONValue = tuple[list[bar_struct.BarStructJSON]]
+UnnamedValue = tuple[bool, int, bar_struct.BarStruct]
+UnnamedSingleValue = tuple[bar_struct.BarStruct]
+
+
+class NamedValue(typing.TypedDict):
+ bool_field: bool
+ u8_field: int
+ nested: bar_struct.BarStruct
+
+
+StructValue = tuple[bar_struct.BarStruct]
+OptionStructValue = tuple[typing.Optional[bar_struct.BarStruct]]
+VecStructValue = tuple[list[bar_struct.BarStruct]]
+
+
+class UnnamedJSON(typing.TypedDict):
+ value: UnnamedJSONValue
+ kind: typing.Literal["Unnamed"]
+
+
+class UnnamedSingleJSON(typing.TypedDict):
+ value: UnnamedSingleJSONValue
+ kind: typing.Literal["UnnamedSingle"]
+
+
+class NamedJSON(typing.TypedDict):
+ value: NamedJSONValue
+ kind: typing.Literal["Named"]
+
+
+class StructJSON(typing.TypedDict):
+ value: StructJSONValue
+ kind: typing.Literal["Struct"]
+
+
+class OptionStructJSON(typing.TypedDict):
+ value: OptionStructJSONValue
+ kind: typing.Literal["OptionStruct"]
+
+
+class VecStructJSON(typing.TypedDict):
+ value: VecStructJSONValue
+ kind: typing.Literal["VecStruct"]
+
+
+class NoFieldsJSON(typing.TypedDict):
+ kind: typing.Literal["NoFields"]
+
+
+@dataclass
+class Unnamed:
+ discriminator: typing.ClassVar = 0
+ kind: typing.ClassVar = "Unnamed"
+ value: UnnamedValue
+
+ def to_json(self) -> UnnamedJSON:
+ return UnnamedJSON(
+ kind="Unnamed",
+ value=(
+ self.value[0],
+ self.value[1],
+ self.value[2].to_json(),
+ ),
+ )
+
+ def to_encodable(self) -> dict:
+ return {
+ "Unnamed": {
+ "item_0": self.value[0],
+ "item_1": self.value[1],
+ "item_2": self.value[2].to_encodable(),
+ },
+ }
+
+
+@dataclass
+class UnnamedSingle:
+ discriminator: typing.ClassVar = 1
+ kind: typing.ClassVar = "UnnamedSingle"
+ value: UnnamedSingleValue
+
+ def to_json(self) -> UnnamedSingleJSON:
+ return UnnamedSingleJSON(
+ kind="UnnamedSingle",
+ value=(self.value[0].to_json(),),
+ )
+
+ def to_encodable(self) -> dict:
+ return {
+ "UnnamedSingle": {
+ "item_0": self.value[0].to_encodable(),
+ },
+ }
+
+
+@dataclass
+class Named:
+ discriminator: typing.ClassVar = 2
+ kind: typing.ClassVar = "Named"
+ value: NamedValue
+
+ def to_json(self) -> NamedJSON:
+ return NamedJSON(
+ kind="Named",
+ value={
+ "bool_field": self.value["bool_field"],
+ "u8_field": self.value["u8_field"],
+ "nested": self.value["nested"].to_json(),
+ },
+ )
+
+ def to_encodable(self) -> dict:
+ return {
+ "Named": {
+ "bool_field": self.value["bool_field"],
+ "u8_field": self.value["u8_field"],
+ "nested": self.value["nested"].to_encodable(),
+ },
+ }
+
+
+@dataclass
+class Struct:
+ discriminator: typing.ClassVar = 3
+ kind: typing.ClassVar = "Struct"
+ value: StructValue
+
+ def to_json(self) -> StructJSON:
+ return StructJSON(
+ kind="Struct",
+ value=(self.value[0].to_json(),),
+ )
+
+ def to_encodable(self) -> dict:
+ return {
+ "Struct": {
+ "item_0": self.value[0].to_encodable(),
+ },
+ }
+
+
+@dataclass
+class OptionStruct:
+ discriminator: typing.ClassVar = 4
+ kind: typing.ClassVar = "OptionStruct"
+ value: OptionStructValue
+
+ def to_json(self) -> OptionStructJSON:
+ return OptionStructJSON(
+ kind="OptionStruct",
+ value=((None if self.value[0] is None else self.value[0].to_json()),),
+ )
+
+ def to_encodable(self) -> dict:
+ return {
+ "OptionStruct": {
+ "item_0": (
+ None if self.value[0] is None else self.value[0].to_encodable()
+ ),
+ },
+ }
+
+
+@dataclass
+class VecStruct:
+ discriminator: typing.ClassVar = 5
+ kind: typing.ClassVar = "VecStruct"
+ value: VecStructValue
+
+ def to_json(self) -> VecStructJSON:
+ return VecStructJSON(
+ kind="VecStruct",
+ value=(list(map(lambda item: item.to_json(), self.value[0])),),
+ )
+
+ def to_encodable(self) -> dict:
+ return {
+ "VecStruct": {
+ "item_0": list(map(lambda item: item.to_encodable(), self.value[0])),
+ },
+ }
+
+
+@dataclass
+class NoFields:
+ discriminator: typing.ClassVar = 6
+ kind: typing.ClassVar = "NoFields"
+
+ @classmethod
+ def to_json(cls) -> NoFieldsJSON:
+ return NoFieldsJSON(
+ kind="NoFields",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "NoFields": {},
+ }
+
+
+FooEnumKind = typing.Union[
+ Unnamed, UnnamedSingle, Named, Struct, OptionStruct, VecStruct, NoFields
+]
+FooEnumJSON = typing.Union[
+ UnnamedJSON,
+ UnnamedSingleJSON,
+ NamedJSON,
+ StructJSON,
+ OptionStructJSON,
+ VecStructJSON,
+ NoFieldsJSON,
+]
+
+
+def from_decoded(obj: dict) -> FooEnumKind:
+ if not isinstance(obj, dict):
+ raise ValueError("Invalid enum object")
+ if "Unnamed" in obj:
+ val = obj["Unnamed"]
+ return Unnamed(
+ (
+ val["item_0"],
+ val["item_1"],
+ bar_struct.BarStruct.from_decoded(val["item_2"]),
+ )
+ )
+ if "UnnamedSingle" in obj:
+ val = obj["UnnamedSingle"]
+ return UnnamedSingle((bar_struct.BarStruct.from_decoded(val["item_0"]),))
+ if "Named" in obj:
+ val = obj["Named"]
+ return Named(
+ NamedValue(
+ bool_field=val["bool_field"],
+ u8_field=val["u8_field"],
+ nested=bar_struct.BarStruct.from_decoded(val["nested"]),
+ )
+ )
+ if "Struct" in obj:
+ val = obj["Struct"]
+ return Struct((bar_struct.BarStruct.from_decoded(val["item_0"]),))
+ if "OptionStruct" in obj:
+ val = obj["OptionStruct"]
+ return OptionStruct(
+ (
+ (
+ None
+ if val["item_0"] is None
+ else bar_struct.BarStruct.from_decoded(val["item_0"])
+ ),
+ )
+ )
+ if "VecStruct" in obj:
+ val = obj["VecStruct"]
+ return VecStruct(
+ (
+ list(
+ map(
+ lambda item: bar_struct.BarStruct.from_decoded(item),
+ val["item_0"],
+ )
+ ),
+ )
+ )
+ if "NoFields" in obj:
+ return NoFields()
+ raise ValueError("Invalid enum object")
+
+
+def from_json(obj: FooEnumJSON) -> FooEnumKind:
+ if obj["kind"] == "Unnamed":
+ unnamed_json_value = typing.cast(UnnamedJSONValue, obj["value"])
+ return Unnamed(
+ (
+ unnamed_json_value[0],
+ unnamed_json_value[1],
+ bar_struct.BarStruct.from_json(unnamed_json_value[2]),
+ )
+ )
+ if obj["kind"] == "UnnamedSingle":
+ unnamed_single_json_value = typing.cast(UnnamedSingleJSONValue, obj["value"])
+ return UnnamedSingle(
+ (bar_struct.BarStruct.from_json(unnamed_single_json_value[0]),)
+ )
+ if obj["kind"] == "Named":
+ named_json_value = typing.cast(NamedJSONValue, obj["value"])
+ return Named(
+ NamedValue(
+ bool_field=named_json_value["bool_field"],
+ u8_field=named_json_value["u8_field"],
+ nested=bar_struct.BarStruct.from_json(named_json_value["nested"]),
+ )
+ )
+ if obj["kind"] == "Struct":
+ struct_json_value = typing.cast(StructJSONValue, obj["value"])
+ return Struct((bar_struct.BarStruct.from_json(struct_json_value[0]),))
+ if obj["kind"] == "OptionStruct":
+ option_struct_json_value = typing.cast(OptionStructJSONValue, obj["value"])
+ return OptionStruct(
+ (
+ (
+ None
+ if option_struct_json_value[0] is None
+ else bar_struct.BarStruct.from_json(option_struct_json_value[0])
+ ),
+ )
+ )
+ if obj["kind"] == "VecStruct":
+ vec_struct_json_value = typing.cast(VecStructJSONValue, obj["value"])
+ return VecStruct(
+ (
+ list(
+ map(
+ lambda item: bar_struct.BarStruct.from_json(item),
+ vec_struct_json_value[0],
+ )
+ ),
+ )
+ )
+ if obj["kind"] == "NoFields":
+ return NoFields()
+ kind = obj["kind"]
+ raise ValueError(f"Unrecognized enum kind: {kind}")
+
+
+layout = EnumForCodegen(
+ "Unnamed"
+ / borsh.CStruct(
+ "item_0" / borsh.Bool,
+ "item_1" / borsh.U8,
+ "item_2" / bar_struct.BarStruct.layout,
+ ),
+ "UnnamedSingle" / borsh.CStruct("item_0" / bar_struct.BarStruct.layout),
+ "Named"
+ / borsh.CStruct(
+ "bool_field" / borsh.Bool,
+ "u8_field" / borsh.U8,
+ "nested" / bar_struct.BarStruct.layout,
+ ),
+ "Struct" / borsh.CStruct("item_0" / bar_struct.BarStruct.layout),
+ "OptionStruct"
+ / borsh.CStruct("item_0" / borsh.Option(bar_struct.BarStruct.layout)),
+ "VecStruct"
+ / borsh.CStruct(
+ "item_0" / borsh.Vec(typing.cast(Construct, bar_struct.BarStruct.layout))
+ ),
+ "NoFields" / borsh.CStruct(),
+)
diff --git a/basics/anchorpy-main/tests/client-gen/example_program_gen/types/foo_struct.py b/basics/anchorpy-main/tests/client-gen/example_program_gen/types/foo_struct.py
new file mode 100644
index 0000000..7db49d8
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/example_program_gen/types/foo_struct.py
@@ -0,0 +1,97 @@
+from __future__ import annotations
+from . import bar_struct, foo_enum
+import typing
+from dataclasses import dataclass
+from construct import Container, Construct
+import borsh_construct as borsh
+
+
+class FooStructJSON(typing.TypedDict):
+ field1: int
+ field2: int
+ nested: bar_struct.BarStructJSON
+ vec_nested: list[bar_struct.BarStructJSON]
+ option_nested: typing.Optional[bar_struct.BarStructJSON]
+ enum_field: foo_enum.FooEnumJSON
+
+
+@dataclass
+class FooStruct:
+ layout: typing.ClassVar = borsh.CStruct(
+ "field1" / borsh.U8,
+ "field2" / borsh.U16,
+ "nested" / bar_struct.BarStruct.layout,
+ "vec_nested" / borsh.Vec(typing.cast(Construct, bar_struct.BarStruct.layout)),
+ "option_nested" / borsh.Option(bar_struct.BarStruct.layout),
+ "enum_field" / foo_enum.layout,
+ )
+ field1: int
+ field2: int
+ nested: bar_struct.BarStruct
+ vec_nested: list[bar_struct.BarStruct]
+ option_nested: typing.Optional[bar_struct.BarStruct]
+ enum_field: foo_enum.FooEnumKind
+
+ @classmethod
+ def from_decoded(cls, obj: Container) -> "FooStruct":
+ return cls(
+ field1=obj.field1,
+ field2=obj.field2,
+ nested=bar_struct.BarStruct.from_decoded(obj.nested),
+ vec_nested=list(
+ map(
+ lambda item: bar_struct.BarStruct.from_decoded(item), obj.vec_nested
+ )
+ ),
+ option_nested=(
+ None
+ if obj.option_nested is None
+ else bar_struct.BarStruct.from_decoded(obj.option_nested)
+ ),
+ enum_field=foo_enum.from_decoded(obj.enum_field),
+ )
+
+ def to_encodable(self) -> dict[str, typing.Any]:
+ return {
+ "field1": self.field1,
+ "field2": self.field2,
+ "nested": self.nested.to_encodable(),
+ "vec_nested": list(map(lambda item: item.to_encodable(), self.vec_nested)),
+ "option_nested": (
+ None
+ if self.option_nested is None
+ else self.option_nested.to_encodable()
+ ),
+ "enum_field": self.enum_field.to_encodable(),
+ }
+
+ def to_json(self) -> FooStructJSON:
+ return {
+ "field1": self.field1,
+ "field2": self.field2,
+ "nested": self.nested.to_json(),
+ "vec_nested": list(map(lambda item: item.to_json(), self.vec_nested)),
+ "option_nested": (
+ None if self.option_nested is None else self.option_nested.to_json()
+ ),
+ "enum_field": self.enum_field.to_json(),
+ }
+
+ @classmethod
+ def from_json(cls, obj: FooStructJSON) -> "FooStruct":
+ return cls(
+ field1=obj["field1"],
+ field2=obj["field2"],
+ nested=bar_struct.BarStruct.from_json(obj["nested"]),
+ vec_nested=list(
+ map(
+ lambda item: bar_struct.BarStruct.from_json(item), obj["vec_nested"]
+ )
+ ),
+ option_nested=(
+ None
+ if obj["option_nested"] is None
+ else bar_struct.BarStruct.from_json(obj["option_nested"])
+ ),
+ enum_field=foo_enum.from_json(obj["enum_field"]),
+ )
diff --git a/basics/anchorpy-main/tests/client-gen/test_client_gen.py b/basics/anchorpy-main/tests/client-gen/test_client_gen.py
new file mode 100644
index 0000000..03f2c3e
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/test_client_gen.py
@@ -0,0 +1,444 @@
+import asyncio
+import json
+from pathlib import Path
+from typing import AsyncGenerator, List
+
+from anchorpy import Provider, Wallet
+from anchorpy.pytest_plugin import localnet_fixture
+from construct import ListContainer
+from pytest import fixture, mark
+from pytest_asyncio import fixture as async_fixture
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Confirmed, Processed
+from solana.rpc.core import RPCException
+from solders.hash import Hash
+from solders.keypair import Keypair
+from solders.message import Message
+from solders.pubkey import Pubkey
+from solders.transaction import VersionedTransaction
+
+from tests.client_gen.example_program_gen.accounts import State, State2
+from tests.client_gen.example_program_gen.errors import from_tx_error
+from tests.client_gen.example_program_gen.errors.custom import SomeError
+from tests.client_gen.example_program_gen.instructions import (
+ InitializeWithValuesAccounts,
+ InitializeWithValuesArgs,
+ cause_error,
+ increment_state_when_present,
+ initialize,
+ initialize_with_values,
+ initialize_with_values2,
+)
+from tests.client_gen.example_program_gen.program_id import PROGRAM_ID
+from tests.client_gen.example_program_gen.types import BarStruct, FooStruct
+from tests.client_gen.example_program_gen.types.foo_enum import (
+ Named,
+ NoFields,
+ Struct,
+ Unnamed,
+)
+
+EXAMPLE_PROGRAM_DIR = Path("tests/client_gen/example-program")
+
+
+@fixture(scope="session")
+def event_loop():
+ """Create an instance of the default event loop for each test case."""
+ loop = asyncio.get_event_loop_policy().new_event_loop()
+ yield loop
+ loop.close()
+
+
+localnet = localnet_fixture(EXAMPLE_PROGRAM_DIR, scope="session")
+
+
+@fixture(scope="session")
+def payer(localnet) -> Keypair:
+ with (EXAMPLE_PROGRAM_DIR / ".anchor/test-ledger/faucet-keypair.json").open() as f:
+ faucet_keypair_json: List[int] = json.load(f)
+ return Keypair.from_bytes(faucet_keypair_json)
+
+
+@async_fixture(scope="session")
+async def provider(localnet, payer: Keypair) -> AsyncGenerator[Provider, None]:
+ wallet = Wallet(payer)
+ conn = AsyncClient(commitment=Processed)
+ prov = Provider(conn, wallet)
+ yield prov
+ await prov.close()
+
+
+@async_fixture(scope="session")
+async def blockhash(provider: Provider) -> Hash:
+ return (await provider.connection.get_latest_blockhash(Confirmed)).value.blockhash
+
+
+@async_fixture(scope="module")
+async def init_and_account_fetch(provider: Provider, blockhash: Hash) -> Keypair:
+ state = Keypair()
+ initialize_ix = initialize(
+ {
+ "state": state.pubkey(),
+ "payer": provider.wallet.public_key,
+ }
+ )
+ msg = Message.new_with_blockhash(
+ [initialize_ix], provider.wallet.public_key, blockhash
+ )
+ tx = VersionedTransaction(msg, [provider.wallet.payer, state])
+ await provider.send(tx)
+ return state
+
+
+@mark.asyncio
+async def test_init_and_account_fetch(
+ init_and_account_fetch: Keypair, provider: Provider
+) -> None:
+ state = init_and_account_fetch
+ vec_struct_field_enum_field_expected = Named(
+ value={
+ "bool_field": True,
+ "u8_field": 15,
+ "nested": BarStruct(some_field=True, other_field=10),
+ }
+ )
+ assert vec_struct_field_enum_field_expected.discriminator == 2
+ assert vec_struct_field_enum_field_expected.kind == "Named"
+ vec_struct_field_expected = [
+ FooStruct(
+ field1=123,
+ field2=999,
+ nested=BarStruct(some_field=True, other_field=10),
+ vec_nested=[BarStruct(some_field=True, other_field=10)],
+ option_nested=BarStruct(some_field=True, other_field=10),
+ enum_field=vec_struct_field_enum_field_expected,
+ )
+ ]
+ option_struct_field_expected = FooStruct(
+ field1=123,
+ field2=999,
+ nested=BarStruct(some_field=True, other_field=10),
+ vec_nested=[BarStruct(some_field=True, other_field=10)],
+ option_nested=BarStruct(some_field=True, other_field=10),
+ enum_field=Named(
+ value={
+ "bool_field": True,
+ "u8_field": 15,
+ "nested": BarStruct(some_field=True, other_field=10),
+ }
+ ),
+ )
+ struct_field_expected = FooStruct(
+ field1=123,
+ field2=999,
+ nested=BarStruct(some_field=True, other_field=10),
+ vec_nested=[BarStruct(some_field=True, other_field=10)],
+ option_nested=BarStruct(some_field=True, other_field=10),
+ enum_field=Named(
+ value={
+ "bool_field": True,
+ "u8_field": 15,
+ "nested": BarStruct(some_field=True, other_field=10),
+ }
+ ),
+ )
+ array_field_expected = ListContainer([True, False, True])
+ vec_field_expected = ListContainer([1, 2, 100, 1000, 18446744073709551615])
+ enum_field1_expected = Unnamed(
+ value=(False, 10, BarStruct(some_field=True, other_field=10))
+ )
+ assert enum_field1_expected.kind == "Unnamed"
+ assert enum_field1_expected.discriminator == 0
+ enum_field2_expected = Named(
+ value={
+ "bool_field": True,
+ "u8_field": 20,
+ "nested": BarStruct(some_field=True, other_field=10),
+ }
+ )
+ assert enum_field2_expected.kind == "Named"
+ assert enum_field2_expected.discriminator == 2
+ enum_field3_expected = Struct(value=(BarStruct(some_field=True, other_field=10),))
+ assert enum_field3_expected.discriminator == 3
+ assert enum_field3_expected.kind == "Struct"
+ enum_field4_expected = NoFields()
+ assert enum_field4_expected.discriminator == 6
+ assert enum_field4_expected.kind == "NoFields"
+ expected = State(
+ bool_field=True,
+ u8_field=234,
+ i8_field=-123,
+ u16_field=62345,
+ i16_field=-31234,
+ u32_field=1234567891,
+ i32_field=-1234567891,
+ f32_field=123456.5,
+ u64_field=9223372036854775817,
+ i64_field=-4611686018427387914,
+ f64_field=1234567891.345,
+ u128_field=170141183460469231731687303715884105737,
+ i128_field=-85070591730234615865843651857942052874,
+ bytes_field=b"\x01\x02\xff\xfe",
+ string_field="hello",
+ pubkey_field=Pubkey.from_string("EPZP2wrcRtMxrAPJCXVEQaYD9eH7fH7h12YqKDcd4aS7"),
+ vec_field=vec_field_expected,
+ vec_struct_field=vec_struct_field_expected,
+ option_field=None,
+ option_struct_field=option_struct_field_expected,
+ struct_field=struct_field_expected,
+ array_field=array_field_expected,
+ enum_field1=enum_field1_expected,
+ enum_field2=enum_field2_expected,
+ enum_field3=enum_field3_expected,
+ enum_field4=enum_field4_expected,
+ )
+ res = await State.fetch(provider.connection, state.pubkey())
+ assert res == expected
+ res = await State.fetch(provider.connection, state.pubkey(), program_id=PROGRAM_ID)
+ assert res == expected
+
+
+@async_fixture(scope="session")
+async def setup_fetch_multiple(
+ provider: Provider, blockhash: Hash
+) -> tuple[Keypair, Keypair]:
+ state = Keypair()
+ another_state = Keypair()
+ initialize_ixs = [
+ initialize(
+ {
+ "state": state.pubkey(),
+ "payer": provider.wallet.public_key,
+ }
+ ),
+ initialize(
+ {
+ "state": another_state.pubkey(),
+ "payer": provider.wallet.public_key,
+ }
+ ),
+ ]
+ msg = Message.new_with_blockhash(
+ initialize_ixs, provider.wallet.public_key, blockhash
+ )
+ tx = VersionedTransaction(msg, [provider.wallet.payer, state, another_state])
+ await provider.send(tx)
+ return state, another_state
+
+
+@mark.asyncio
+async def test_fetch_multiple(
+ provider: Provider, setup_fetch_multiple: tuple[Keypair, Keypair]
+) -> None:
+ state, another_state = setup_fetch_multiple
+ non_state = Keypair()
+ res = await State.fetch_multiple(
+ provider.connection,
+ [state.pubkey(), non_state.pubkey(), another_state.pubkey()],
+ )
+ assert isinstance(res[0], State)
+ assert res[1] is None
+ assert isinstance(res[2], State)
+
+
+@async_fixture(scope="session")
+async def send_instructions_with_args(
+ provider: Provider, blockhash
+) -> tuple[Keypair, Keypair]:
+ state = Keypair()
+ state2 = Keypair()
+ vec_struct_field = [
+ FooStruct(
+ field1=1,
+ field2=2,
+ nested=BarStruct(some_field=True, other_field=55),
+ vec_nested=[BarStruct(some_field=False, other_field=11)],
+ option_nested=None,
+ enum_field=Unnamed((True, 22, BarStruct(some_field=True, other_field=33))),
+ )
+ ]
+ struct_field = FooStruct(
+ field1=1,
+ field2=2,
+ nested=BarStruct(some_field=True, other_field=55),
+ vec_nested=[BarStruct(some_field=False, other_field=11)],
+ option_nested=None,
+ enum_field=NoFields(),
+ )
+ enum_field1 = Unnamed((True, 15, BarStruct(some_field=False, other_field=200)))
+ enum_field2 = Named(
+ {
+ "bool_field": True,
+ "u8_field": 128,
+ "nested": BarStruct(some_field=False, other_field=1),
+ }
+ )
+ enum_field3 = Struct((BarStruct(some_field=True, other_field=15),))
+ initialize_with_values_args = InitializeWithValuesArgs(
+ bool_field=True,
+ u8_field=253,
+ i8_field=-120,
+ u16_field=61234,
+ i16_field=-31253,
+ u32_field=1234567899,
+ i32_field=-123456789,
+ f32_field=123458.5,
+ u64_field=9223372036854775810,
+ i64_field=-4611686018427387912,
+ f64_field=1234567892.445,
+ u128_field=170141183460469231731687303715884105740,
+ i128_field=-85070591730234615865843651857942052877,
+ bytes_field=bytes([5, 10, 255]),
+ string_field="string value",
+ pubkey_field=Pubkey.from_string("GDddEKTjLBqhskzSMYph5o54VYLQfPCR3PoFqKHLJK6s"),
+ vec_field=[1, 123456789123456789],
+ vec_struct_field=vec_struct_field,
+ option_field=True,
+ option_struct_field=None,
+ struct_field=struct_field,
+ array_field=[True, True, False],
+ enum_field1=enum_field1,
+ enum_field2=enum_field2,
+ enum_field3=enum_field3,
+ enum_field4=NoFields(),
+ )
+ initialize_with_values_accounts = InitializeWithValuesAccounts(
+ state=state.pubkey(),
+ payer=provider.wallet.public_key,
+ )
+ ix1 = initialize_with_values(
+ initialize_with_values_args, initialize_with_values_accounts
+ )
+ ix2 = initialize_with_values2(
+ {"vec_of_option": [None, None, 20]},
+ {
+ "state": state2.pubkey(),
+ "payer": provider.wallet.public_key,
+ },
+ )
+ msg = Message.new_with_blockhash([ix1, ix2], provider.wallet.public_key, blockhash)
+ tx = VersionedTransaction(msg, [provider.wallet.payer, state, state2])
+ await provider.send(tx)
+ return state, state2
+
+
+@mark.asyncio
+async def test_instructions_with_args(
+ send_instructions_with_args: tuple[Keypair, Keypair], provider: Provider
+) -> None:
+ state, state2 = send_instructions_with_args
+ expected = State(
+ bool_field=True,
+ u8_field=253,
+ i8_field=-120,
+ u16_field=61234,
+ i16_field=-31253,
+ u32_field=1234567899,
+ i32_field=-123456789,
+ f32_field=123458.5,
+ u64_field=9223372036854775810,
+ i64_field=-4611686018427387912,
+ f64_field=1234567892.445,
+ u128_field=170141183460469231731687303715884105740,
+ i128_field=-85070591730234615865843651857942052877,
+ bytes_field=b"\x05\n\xff",
+ string_field="string value",
+ pubkey_field=Pubkey.from_string("GDddEKTjLBqhskzSMYph5o54VYLQfPCR3PoFqKHLJK6s"),
+ vec_field=ListContainer([1, 123456789123456789]),
+ vec_struct_field=[
+ FooStruct(
+ field1=1,
+ field2=2,
+ nested=BarStruct(some_field=True, other_field=55),
+ vec_nested=[BarStruct(some_field=False, other_field=11)],
+ option_nested=None,
+ enum_field=Unnamed(
+ value=(True, 22, BarStruct(some_field=True, other_field=33))
+ ),
+ )
+ ],
+ option_field=True,
+ option_struct_field=None,
+ struct_field=FooStruct(
+ field1=1,
+ field2=2,
+ nested=BarStruct(some_field=True, other_field=55),
+ vec_nested=[BarStruct(some_field=False, other_field=11)],
+ option_nested=None,
+ enum_field=NoFields(),
+ ),
+ array_field=ListContainer([True, True, False]),
+ enum_field1=Unnamed(
+ value=(True, 15, BarStruct(some_field=False, other_field=200))
+ ),
+ enum_field2=Named(
+ value={
+ "bool_field": True,
+ "u8_field": 128,
+ "nested": BarStruct(some_field=False, other_field=1),
+ }
+ ),
+ enum_field3=Struct(value=(BarStruct(some_field=True, other_field=15),)),
+ enum_field4=NoFields(),
+ )
+ expected2 = State2(vec_of_option=ListContainer([None, None, 20]))
+ res = await State.fetch(provider.connection, state.pubkey())
+ res2 = await State2.fetch(provider.connection, state2.pubkey())
+ assert res == expected
+ assert res2 == expected2
+
+
+@mark.asyncio
+async def test_instruction_with_optional_account(
+ send_instructions_with_args: tuple[Keypair, Keypair],
+ provider: Provider,
+ blockhash: Hash,
+) -> None:
+ def prepare_tx(ixs):
+ msg = Message.new_with_blockhash([ix], provider.wallet.public_key, blockhash)
+ tx = VersionedTransaction(msg, [provider.wallet.payer])
+ return tx
+
+ state, state2 = send_instructions_with_args
+ ix = increment_state_when_present(
+ {
+ "first_state": None,
+ "second_state": state2.pubkey(),
+ },
+ )
+ before_res = await State.fetch(provider.connection, state.pubkey())
+ assert before_res is not None
+ tx = prepare_tx(ix)
+ await provider.send(tx)
+
+ res = await State.fetch(provider.connection, state.pubkey())
+ assert res is not None
+ assert before_res.u8_field == res.u8_field
+
+ ix = increment_state_when_present(
+ {
+ "first_state": state.pubkey(),
+ "second_state": state2.pubkey(),
+ },
+ )
+
+ res = await State.fetch(provider.connection, state.pubkey())
+ tx = prepare_tx(ix)
+ await provider.send(tx)
+
+ res = await State.fetch(provider.connection, state.pubkey())
+ assert res is not None
+ assert before_res.u8_field + 1 == res.u8_field
+
+
+@mark.asyncio
+async def test_cause_error(provider: Provider, blockhash: Hash) -> None:
+ msg = Message.new_with_blockhash(
+ [cause_error()], provider.wallet.public_key, blockhash
+ )
+ tx = VersionedTransaction(msg, [provider.wallet.payer])
+ try:
+ await provider.send(tx)
+ except RPCException as exc:
+ caught = from_tx_error(exc)
+ assert isinstance(caught, SomeError)
diff --git a/basics/anchorpy-main/tests/client-gen/test_functional.py b/basics/anchorpy-main/tests/client-gen/test_functional.py
new file mode 100644
index 0000000..aa3d2db
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/test_functional.py
@@ -0,0 +1,357 @@
+import json
+from filecmp import dircmp
+from pathlib import Path
+
+from anchorpy.cli import client_gen
+from py.path import local
+from solana.rpc.core import RPCException
+from solders.pubkey import Pubkey
+from solders.rpc.errors import SendTransactionPreflightFailureMessage
+from solders.rpc.responses import SimulateTransactionResp
+
+from tests.client_gen.example_program_gen.accounts import State
+from tests.client_gen.example_program_gen.errors import from_tx_error
+from tests.client_gen.example_program_gen.errors.anchor import InvalidProgramId
+from tests.client_gen.example_program_gen.types import BarStruct, FooStruct
+from tests.client_gen.example_program_gen.types.foo_enum import (
+ Named,
+ NamedValue,
+ NoFields,
+ Struct,
+ Unnamed,
+)
+
+
+def test_quarry_mine(tmpdir: local) -> None:
+ proj_dir = Path(tmpdir)
+ out_dir = proj_dir / "generated"
+ idl_path = Path("tests/idls/quarry_mine.json")
+ client_gen(idl_path, out_dir, "placeholder")
+
+
+def test_merkle_distributor(tmpdir: local) -> None:
+ proj_dir = Path(tmpdir)
+ out_dir = proj_dir / "generated"
+ idl_path = Path("tests/idls/merkle_distributor.json")
+ client_gen(idl_path, out_dir, "placeholder")
+
+
+def test_null_err_when_cpi_fails() -> None:
+ to_dump = {
+ "jsonrpc": "2.0",
+ "error": {
+ "code": -32002,
+ "message": "",
+ "data": {
+ "err": {"InstructionError": [0, {"Custom": 3}]},
+ "logs": [
+ "Program 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 invoke [1]",
+ "Program log: Instruction: CauseError",
+ "Program 11111111111111111111111111111111 invoke [2]",
+ "Allocate: requested 1000000000000000000, max allowed 10485760",
+ "Program 11111111111111111111111111111111 failed: custom program error: 0x3",
+ "Program 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 consumed 7958 of 1400000 compute units",
+ "Program 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 failed: custom program error: 0x3",
+ ],
+ },
+ },
+ }
+ raw = json.dumps(to_dump)
+ parsed = SimulateTransactionResp.from_json(raw)
+ assert isinstance(parsed, SendTransactionPreflightFailureMessage)
+ err_mock = RPCException(parsed)
+ assert from_tx_error(err_mock) is None
+
+
+def test_parses_anchor_error() -> None:
+ to_dump = {
+ "jsonrpc": "2.0",
+ "error": {
+ "code": -32002,
+ "message": "",
+ "data": {
+ "err": {"InstructionError": [0, {"Custom": 3008}]},
+ "logs": [
+ "Program 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 invoke [1]",
+ "Program log: Instruction: CauseError",
+ "Program log: AnchorError caused by account: system_program. Error Code: InvalidProgramId. Error Number: 3008. Error Message: Program ID was not as expected.",
+ "Program log: Left:",
+ "Program log: 24S58Cp5Myf6iGx4umBNd7RgDrZ9nkKzvkfFHBMDomNa",
+ "Program log: Right:",
+ "Program log: 11111111111111111111111111111111",
+ "Program 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 consumed 5043 of 1400000 compute units",
+ "Program 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 failed: custom program error: 0xbc0",
+ ],
+ },
+ },
+ }
+ raw = json.dumps(to_dump)
+ parsed = SimulateTransactionResp.from_json(raw)
+ assert isinstance(parsed, SendTransactionPreflightFailureMessage)
+ err_mock = RPCException(parsed)
+ assert isinstance(from_tx_error(err_mock), InvalidProgramId)
+
+
+def test_json() -> None:
+ vec_struct_field = [
+ FooStruct(
+ field1=5,
+ field2=6,
+ nested=BarStruct(
+ some_field=True,
+ other_field=15,
+ ),
+ vec_nested=[
+ BarStruct(
+ some_field=True,
+ other_field=13,
+ ),
+ ],
+ option_nested=None,
+ enum_field=Unnamed(
+ (
+ False,
+ 111,
+ BarStruct(
+ some_field=False,
+ other_field=11,
+ ),
+ )
+ ),
+ ),
+ ]
+ option_struct_field = FooStruct(
+ field1=8,
+ field2=9,
+ nested=BarStruct(
+ some_field=True,
+ other_field=17,
+ ),
+ vec_nested=[
+ BarStruct(
+ some_field=True,
+ other_field=10,
+ ),
+ ],
+ option_nested=BarStruct(
+ some_field=False,
+ other_field=99,
+ ),
+ enum_field=NoFields(),
+ )
+ struct_field = FooStruct(
+ field1=11,
+ field2=12,
+ nested=BarStruct(
+ some_field=False,
+ other_field=177,
+ ),
+ vec_nested=[
+ BarStruct(
+ some_field=True,
+ other_field=15,
+ ),
+ ],
+ option_nested=BarStruct(
+ some_field=True,
+ other_field=75,
+ ),
+ enum_field=NoFields(),
+ )
+ enum_field1 = Unnamed(
+ (
+ False,
+ 157,
+ BarStruct(
+ some_field=True,
+ other_field=193,
+ ),
+ )
+ )
+ enum_field2 = Named(
+ NamedValue(
+ bool_field=False,
+ u8_field=77,
+ nested=BarStruct(
+ some_field=True,
+ other_field=100,
+ ),
+ )
+ )
+ enum_field3 = Struct(
+ (
+ BarStruct(
+ some_field=False,
+ other_field=122,
+ ),
+ )
+ )
+ state = State(
+ bool_field=True,
+ u8_field=255,
+ i8_field=-120,
+ u16_field=62000,
+ i16_field=-31000,
+ u32_field=123456789,
+ i32_field=-123456789,
+ f32_field=123456.5,
+ u64_field=9223372036854775805,
+ i64_field=4611686018427387910,
+ f64_field=1234567891.35,
+ u128_field=170141183460469231731687303715884105760,
+ i128_field=-85070591730234615865843651857942052897,
+ bytes_field=bytes([1, 255]),
+ string_field="a string",
+ pubkey_field=Pubkey.from_string("EPZP2wrcRtMxrAPJCXVEQaYD9eH7fH7h12YqKDcd4aS7"),
+ vec_field=[10, 1234567890123456],
+ vec_struct_field=vec_struct_field,
+ option_field=None,
+ option_struct_field=option_struct_field,
+ struct_field=struct_field,
+ array_field=[True, False],
+ enum_field1=enum_field1,
+ enum_field2=enum_field2,
+ enum_field3=enum_field3,
+ enum_field4=NoFields(),
+ )
+ state_json = state.to_json()
+ expected = {
+ "bool_field": True,
+ "u8_field": 255,
+ "i8_field": -120,
+ "u16_field": 62000,
+ "i16_field": -31000,
+ "u32_field": 123456789,
+ "i32_field": -123456789,
+ "f32_field": 123456.5,
+ "u64_field": 9223372036854775805,
+ "i64_field": 4611686018427387910,
+ "f64_field": 1234567891.35,
+ "u128_field": 170141183460469231731687303715884105760,
+ "i128_field": -85070591730234615865843651857942052897,
+ "bytes_field": [1, 255],
+ "string_field": "a string",
+ "pubkey_field": "EPZP2wrcRtMxrAPJCXVEQaYD9eH7fH7h12YqKDcd4aS7",
+ "vec_field": [10, 1234567890123456],
+ "vec_struct_field": [
+ {
+ "field1": 5,
+ "field2": 6,
+ "nested": {
+ "some_field": True,
+ "other_field": 15,
+ },
+ "vec_nested": [
+ {
+ "some_field": True,
+ "other_field": 13,
+ },
+ ],
+ "option_nested": None,
+ "enum_field": {
+ "kind": "Unnamed",
+ "value": (
+ False,
+ 111,
+ {
+ "some_field": False,
+ "other_field": 11,
+ },
+ ),
+ },
+ },
+ ],
+ "option_field": None,
+ "option_struct_field": {
+ "field1": 8,
+ "field2": 9,
+ "nested": {
+ "some_field": True,
+ "other_field": 17,
+ },
+ "vec_nested": [
+ {
+ "some_field": True,
+ "other_field": 10,
+ },
+ ],
+ "option_nested": {
+ "some_field": False,
+ "other_field": 99,
+ },
+ "enum_field": {
+ "kind": "NoFields",
+ },
+ },
+ "struct_field": {
+ "field1": 11,
+ "field2": 12,
+ "nested": {
+ "some_field": False,
+ "other_field": 177,
+ },
+ "vec_nested": [
+ {
+ "some_field": True,
+ "other_field": 15,
+ },
+ ],
+ "option_nested": {
+ "some_field": True,
+ "other_field": 75,
+ },
+ "enum_field": {
+ "kind": "NoFields",
+ },
+ },
+ "array_field": [True, False],
+ "enum_field1": {
+ "kind": "Unnamed",
+ "value": (
+ False,
+ 157,
+ {
+ "some_field": True,
+ "other_field": 193,
+ },
+ ),
+ },
+ "enum_field2": {
+ "kind": "Named",
+ "value": {
+ "bool_field": False,
+ "u8_field": 77,
+ "nested": {
+ "some_field": True,
+ "other_field": 100,
+ },
+ },
+ },
+ "enum_field3": {
+ "kind": "Struct",
+ "value": (
+ {
+ "some_field": False,
+ "other_field": 122,
+ },
+ ),
+ },
+ "enum_field4": {
+ "kind": "NoFields",
+ },
+ }
+ assert state_json == expected
+ state_from_json = State.from_json(state_json)
+ assert state_from_json == state
+
+
+def has_differences(dcmp: dircmp) -> bool:
+ differences = dcmp.left_only + dcmp.right_only + dcmp.diff_files
+ if differences:
+ return True
+ return any([has_differences(subdcmp) for subdcmp in dcmp.subdirs.values()])
+
+
+def test_generated_as_expected(project_dir: Path) -> None:
+ dcmp = dircmp(project_dir, "tests/client_gen/example_program_gen")
+ assert not has_differences(dcmp)
diff --git a/basics/anchorpy-main/tests/client-gen/token/__init__.py b/basics/anchorpy-main/tests/client-gen/token/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/basics/anchorpy-main/tests/client-gen/token/accounts/__init__.py b/basics/anchorpy-main/tests/client-gen/token/accounts/__init__.py
new file mode 100644
index 0000000..95f3234
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/accounts/__init__.py
@@ -0,0 +1,3 @@
+from .mint import Mint, MintJSON
+from .account import Account, AccountJSON
+from .multisig import Multisig, MultisigJSON
diff --git a/basics/anchorpy-main/tests/client-gen/token/accounts/account.py b/basics/anchorpy-main/tests/client-gen/token/accounts/account.py
new file mode 100644
index 0000000..d85015e
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/accounts/account.py
@@ -0,0 +1,133 @@
+import typing
+from dataclasses import dataclass
+from solders.pubkey import Pubkey
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+import borsh_construct as borsh
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.error import AccountInvalidDiscriminator
+from anchorpy.utils.rpc import get_multiple_accounts
+from anchorpy.borsh_extension import BorshPubkey, COption
+from ..program_id import PROGRAM_ID
+from .. import types
+
+
+class AccountJSON(typing.TypedDict):
+ mint: str
+ owner: str
+ amount: int
+ delegate: typing.Optional[str]
+ state: types.account_state.AccountStateJSON
+ is_native: typing.Optional[int]
+ delegated_amount: int
+ close_authority: typing.Optional[str]
+
+
+@dataclass
+class Account:
+ discriminator: typing.ClassVar = b"qB\xe06\xbcw\xf0e"
+ layout: typing.ClassVar = borsh.CStruct(
+ "mint" / BorshPubkey,
+ "owner" / BorshPubkey,
+ "amount" / borsh.U64,
+ "delegate" / COption(BorshPubkey),
+ "state" / types.account_state.layout,
+ "is_native" / COption(borsh.U64),
+ "delegated_amount" / borsh.U64,
+ "close_authority" / COption(BorshPubkey),
+ )
+ mint: Pubkey
+ owner: Pubkey
+ amount: int
+ delegate: typing.Optional[Pubkey]
+ state: types.account_state.AccountStateKind
+ is_native: typing.Optional[int]
+ delegated_amount: int
+ close_authority: typing.Optional[Pubkey]
+
+ @classmethod
+ async def fetch(
+ cls,
+ conn: AsyncClient,
+ address: Pubkey,
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.Optional["Account"]:
+ resp = await conn.get_account_info(address, commitment=commitment)
+ info = resp.value
+ if info is None:
+ return None
+ if info.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ bytes_data = info.data
+ return cls.decode(bytes_data)
+
+ @classmethod
+ async def fetch_multiple(
+ cls,
+ conn: AsyncClient,
+ addresses: list[Pubkey],
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.List[typing.Optional["Account"]]:
+ infos = await get_multiple_accounts(conn, addresses, commitment=commitment)
+ res: typing.List[typing.Optional["Account"]] = []
+ for info in infos:
+ if info is None:
+ res.append(None)
+ continue
+ if info.account.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ res.append(cls.decode(info.account.data))
+ return res
+
+ @classmethod
+ def decode(cls, data: bytes) -> "Account":
+ if data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator:
+ raise AccountInvalidDiscriminator(
+ "The discriminator for this account is invalid"
+ )
+ dec = Account.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])
+ return cls(
+ mint=dec.mint,
+ owner=dec.owner,
+ amount=dec.amount,
+ delegate=dec.delegate,
+ state=types.account_state.from_decoded(dec.state),
+ is_native=dec.is_native,
+ delegated_amount=dec.delegated_amount,
+ close_authority=dec.close_authority,
+ )
+
+ def to_json(self) -> AccountJSON:
+ return {
+ "mint": str(self.mint),
+ "owner": str(self.owner),
+ "amount": self.amount,
+ "delegate": (None if self.delegate is None else str(self.delegate)),
+ "state": self.state.to_json(),
+ "is_native": self.is_native,
+ "delegated_amount": self.delegated_amount,
+ "close_authority": (
+ None if self.close_authority is None else str(self.close_authority)
+ ),
+ }
+
+ @classmethod
+ def from_json(cls, obj: AccountJSON) -> "Account":
+ return cls(
+ mint=Pubkey.from_string(obj["mint"]),
+ owner=Pubkey.from_string(obj["owner"]),
+ amount=obj["amount"],
+ delegate=(
+ None if obj["delegate"] is None else Pubkey.from_string(obj["delegate"])
+ ),
+ state=types.account_state.from_json(obj["state"]),
+ is_native=obj["is_native"],
+ delegated_amount=obj["delegated_amount"],
+ close_authority=(
+ None
+ if obj["close_authority"] is None
+ else Pubkey.from_string(obj["close_authority"])
+ ),
+ )
diff --git a/basics/anchorpy-main/tests/client-gen/token/accounts/mint.py b/basics/anchorpy-main/tests/client-gen/token/accounts/mint.py
new file mode 100644
index 0000000..8df31bb
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/accounts/mint.py
@@ -0,0 +1,118 @@
+import typing
+from dataclasses import dataclass
+from solders.pubkey import Pubkey
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+import borsh_construct as borsh
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.error import AccountInvalidDiscriminator
+from anchorpy.utils.rpc import get_multiple_accounts
+from anchorpy.borsh_extension import BorshPubkey, COption
+from ..program_id import PROGRAM_ID
+
+
+class MintJSON(typing.TypedDict):
+ mint_authority: typing.Optional[str]
+ supply: int
+ decimals: int
+ is_initialized: bool
+ freeze_authority: typing.Optional[str]
+
+
+@dataclass
+class Mint:
+ discriminator: typing.ClassVar = b"P\xbc\xf5\x14_\x8a9\x9c"
+ layout: typing.ClassVar = borsh.CStruct(
+ "mint_authority" / COption(BorshPubkey),
+ "supply" / borsh.U64,
+ "decimals" / borsh.U8,
+ "is_initialized" / borsh.Bool,
+ "freeze_authority" / COption(BorshPubkey),
+ )
+ mint_authority: typing.Optional[Pubkey]
+ supply: int
+ decimals: int
+ is_initialized: bool
+ freeze_authority: typing.Optional[Pubkey]
+
+ @classmethod
+ async def fetch(
+ cls,
+ conn: AsyncClient,
+ address: Pubkey,
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.Optional["Mint"]:
+ resp = await conn.get_account_info(address, commitment=commitment)
+ info = resp.value
+ if info is None:
+ return None
+ if info.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ bytes_data = info.data
+ return cls.decode(bytes_data)
+
+ @classmethod
+ async def fetch_multiple(
+ cls,
+ conn: AsyncClient,
+ addresses: list[Pubkey],
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.List[typing.Optional["Mint"]]:
+ infos = await get_multiple_accounts(conn, addresses, commitment=commitment)
+ res: typing.List[typing.Optional["Mint"]] = []
+ for info in infos:
+ if info is None:
+ res.append(None)
+ continue
+ if info.account.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ res.append(cls.decode(info.account.data))
+ return res
+
+ @classmethod
+ def decode(cls, data: bytes) -> "Mint":
+ if data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator:
+ raise AccountInvalidDiscriminator(
+ "The discriminator for this account is invalid"
+ )
+ dec = Mint.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])
+ return cls(
+ mint_authority=dec.mint_authority,
+ supply=dec.supply,
+ decimals=dec.decimals,
+ is_initialized=dec.is_initialized,
+ freeze_authority=dec.freeze_authority,
+ )
+
+ def to_json(self) -> MintJSON:
+ return {
+ "mint_authority": (
+ None if self.mint_authority is None else str(self.mint_authority)
+ ),
+ "supply": self.supply,
+ "decimals": self.decimals,
+ "is_initialized": self.is_initialized,
+ "freeze_authority": (
+ None if self.freeze_authority is None else str(self.freeze_authority)
+ ),
+ }
+
+ @classmethod
+ def from_json(cls, obj: MintJSON) -> "Mint":
+ return cls(
+ mint_authority=(
+ None
+ if obj["mint_authority"] is None
+ else Pubkey.from_string(obj["mint_authority"])
+ ),
+ supply=obj["supply"],
+ decimals=obj["decimals"],
+ is_initialized=obj["is_initialized"],
+ freeze_authority=(
+ None
+ if obj["freeze_authority"] is None
+ else Pubkey.from_string(obj["freeze_authority"])
+ ),
+ )
diff --git a/basics/anchorpy-main/tests/client-gen/token/accounts/multisig.py b/basics/anchorpy-main/tests/client-gen/token/accounts/multisig.py
new file mode 100644
index 0000000..3b63a5c
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/accounts/multisig.py
@@ -0,0 +1,100 @@
+import typing
+from dataclasses import dataclass
+from solders.pubkey import Pubkey
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+import borsh_construct as borsh
+from anchorpy.coder.accounts import ACCOUNT_DISCRIMINATOR_SIZE
+from anchorpy.error import AccountInvalidDiscriminator
+from anchorpy.utils.rpc import get_multiple_accounts
+from anchorpy.borsh_extension import BorshPubkey
+from ..program_id import PROGRAM_ID
+
+
+class MultisigJSON(typing.TypedDict):
+ m: int
+ n: int
+ is_initialized: bool
+ signers: list[str]
+
+
+@dataclass
+class Multisig:
+ discriminator: typing.ClassVar = b"\xe0ty\xbaD\xa1O\xec"
+ layout: typing.ClassVar = borsh.CStruct(
+ "m" / borsh.U8,
+ "n" / borsh.U8,
+ "is_initialized" / borsh.Bool,
+ "signers" / BorshPubkey[11],
+ )
+ m: int
+ n: int
+ is_initialized: bool
+ signers: list[Pubkey]
+
+ @classmethod
+ async def fetch(
+ cls,
+ conn: AsyncClient,
+ address: Pubkey,
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.Optional["Multisig"]:
+ resp = await conn.get_account_info(address, commitment=commitment)
+ info = resp.value
+ if info is None:
+ return None
+ if info.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ bytes_data = info.data
+ return cls.decode(bytes_data)
+
+ @classmethod
+ async def fetch_multiple(
+ cls,
+ conn: AsyncClient,
+ addresses: list[Pubkey],
+ commitment: typing.Optional[Commitment] = None,
+ program_id: Pubkey = PROGRAM_ID,
+ ) -> typing.List[typing.Optional["Multisig"]]:
+ infos = await get_multiple_accounts(conn, addresses, commitment=commitment)
+ res: typing.List[typing.Optional["Multisig"]] = []
+ for info in infos:
+ if info is None:
+ res.append(None)
+ continue
+ if info.account.owner != program_id:
+ raise ValueError("Account does not belong to this program")
+ res.append(cls.decode(info.account.data))
+ return res
+
+ @classmethod
+ def decode(cls, data: bytes) -> "Multisig":
+ if data[:ACCOUNT_DISCRIMINATOR_SIZE] != cls.discriminator:
+ raise AccountInvalidDiscriminator(
+ "The discriminator for this account is invalid"
+ )
+ dec = Multisig.layout.parse(data[ACCOUNT_DISCRIMINATOR_SIZE:])
+ return cls(
+ m=dec.m,
+ n=dec.n,
+ is_initialized=dec.is_initialized,
+ signers=dec.signers,
+ )
+
+ def to_json(self) -> MultisigJSON:
+ return {
+ "m": self.m,
+ "n": self.n,
+ "is_initialized": self.is_initialized,
+ "signers": list(map(lambda item: str(item), self.signers)),
+ }
+
+ @classmethod
+ def from_json(cls, obj: MultisigJSON) -> "Multisig":
+ return cls(
+ m=obj["m"],
+ n=obj["n"],
+ is_initialized=obj["is_initialized"],
+ signers=list(map(lambda item: Pubkey.from_string(item), obj["signers"])),
+ )
diff --git a/basics/anchorpy-main/tests/client-gen/token/errors/__init__.py b/basics/anchorpy-main/tests/client-gen/token/errors/__init__.py
new file mode 100644
index 0000000..421993d
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/errors/__init__.py
@@ -0,0 +1,29 @@
+import typing
+import re
+from solders.transaction_status import (
+ InstructionErrorCustom,
+ TransactionErrorInstructionError,
+)
+from solana.rpc.core import RPCException
+from solders.rpc.errors import SendTransactionPreflightFailureMessage
+from anchorpy.error import extract_code_and_logs
+from ..program_id import PROGRAM_ID
+from . import anchor
+from . import custom
+
+
+def from_code(code: int) -> typing.Union[custom.CustomError, anchor.AnchorError, None]:
+ return custom.from_code(code) if code >= 6000 else anchor.from_code(code)
+
+
+error_re = re.compile(r"Program (\w+) failed: custom program error: (\w+)")
+
+
+def from_tx_error(
+ error: RPCException,
+) -> typing.Union[anchor.AnchorError, custom.CustomError, None]:
+ err_info = error.args[0]
+ extracted = extract_code_and_logs(err_info, PROGRAM_ID)
+ if extracted is None:
+ return None
+ return from_code(extracted[0])
diff --git a/basics/anchorpy-main/tests/client-gen/token/errors/anchor.py b/basics/anchorpy-main/tests/client-gen/token/errors/anchor.py
new file mode 100644
index 0000000..3f266ef
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/errors/anchor.py
@@ -0,0 +1,590 @@
+import typing
+from anchorpy.error import ProgramError
+
+
+class InstructionMissing(ProgramError):
+ def __init__(self):
+ super().__init__(100, "8 byte instruction identifier not provided")
+
+ code = 100
+ name = "InstructionMissing"
+ msg = "8 byte instruction identifier not provided"
+
+
+class InstructionFallbackNotFound(ProgramError):
+ def __init__(self):
+ super().__init__(101, "Fallback functions are not supported")
+
+ code = 101
+ name = "InstructionFallbackNotFound"
+ msg = "Fallback functions are not supported"
+
+
+class InstructionDidNotDeserialize(ProgramError):
+ def __init__(self):
+ super().__init__(102, "The program could not deserialize the given instruction")
+
+ code = 102
+ name = "InstructionDidNotDeserialize"
+ msg = "The program could not deserialize the given instruction"
+
+
+class InstructionDidNotSerialize(ProgramError):
+ def __init__(self):
+ super().__init__(103, "The program could not serialize the given instruction")
+
+ code = 103
+ name = "InstructionDidNotSerialize"
+ msg = "The program could not serialize the given instruction"
+
+
+class IdlInstructionStub(ProgramError):
+ def __init__(self):
+ super().__init__(1000, "The program was compiled without idl instructions")
+
+ code = 1000
+ name = "IdlInstructionStub"
+ msg = "The program was compiled without idl instructions"
+
+
+class IdlInstructionInvalidProgram(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 1001, "The transaction was given an invalid program for the IDL instruction"
+ )
+
+ code = 1001
+ name = "IdlInstructionInvalidProgram"
+ msg = "The transaction was given an invalid program for the IDL instruction"
+
+
+class ConstraintMut(ProgramError):
+ def __init__(self):
+ super().__init__(2000, "A mut constraint was violated")
+
+ code = 2000
+ name = "ConstraintMut"
+ msg = "A mut constraint was violated"
+
+
+class ConstraintHasOne(ProgramError):
+ def __init__(self):
+ super().__init__(2001, "A has_one constraint was violated")
+
+ code = 2001
+ name = "ConstraintHasOne"
+ msg = "A has_one constraint was violated"
+
+
+class ConstraintSigner(ProgramError):
+ def __init__(self):
+ super().__init__(2002, "A signer constraint was violated")
+
+ code = 2002
+ name = "ConstraintSigner"
+ msg = "A signer constraint was violated"
+
+
+class ConstraintRaw(ProgramError):
+ def __init__(self):
+ super().__init__(2003, "A raw constraint was violated")
+
+ code = 2003
+ name = "ConstraintRaw"
+ msg = "A raw constraint was violated"
+
+
+class ConstraintOwner(ProgramError):
+ def __init__(self):
+ super().__init__(2004, "An owner constraint was violated")
+
+ code = 2004
+ name = "ConstraintOwner"
+ msg = "An owner constraint was violated"
+
+
+class ConstraintRentExempt(ProgramError):
+ def __init__(self):
+ super().__init__(2005, "A rent exempt constraint was violated")
+
+ code = 2005
+ name = "ConstraintRentExempt"
+ msg = "A rent exempt constraint was violated"
+
+
+class ConstraintSeeds(ProgramError):
+ def __init__(self):
+ super().__init__(2006, "A seeds constraint was violated")
+
+ code = 2006
+ name = "ConstraintSeeds"
+ msg = "A seeds constraint was violated"
+
+
+class ConstraintExecutable(ProgramError):
+ def __init__(self):
+ super().__init__(2007, "An executable constraint was violated")
+
+ code = 2007
+ name = "ConstraintExecutable"
+ msg = "An executable constraint was violated"
+
+
+class ConstraintState(ProgramError):
+ def __init__(self):
+ super().__init__(2008, "A state constraint was violated")
+
+ code = 2008
+ name = "ConstraintState"
+ msg = "A state constraint was violated"
+
+
+class ConstraintAssociated(ProgramError):
+ def __init__(self):
+ super().__init__(2009, "An associated constraint was violated")
+
+ code = 2009
+ name = "ConstraintAssociated"
+ msg = "An associated constraint was violated"
+
+
+class ConstraintAssociatedInit(ProgramError):
+ def __init__(self):
+ super().__init__(2010, "An associated init constraint was violated")
+
+ code = 2010
+ name = "ConstraintAssociatedInit"
+ msg = "An associated init constraint was violated"
+
+
+class ConstraintClose(ProgramError):
+ def __init__(self):
+ super().__init__(2011, "A close constraint was violated")
+
+ code = 2011
+ name = "ConstraintClose"
+ msg = "A close constraint was violated"
+
+
+class ConstraintAddress(ProgramError):
+ def __init__(self):
+ super().__init__(2012, "An address constraint was violated")
+
+ code = 2012
+ name = "ConstraintAddress"
+ msg = "An address constraint was violated"
+
+
+class ConstraintZero(ProgramError):
+ def __init__(self):
+ super().__init__(2013, "Expected zero account discriminant")
+
+ code = 2013
+ name = "ConstraintZero"
+ msg = "Expected zero account discriminant"
+
+
+class ConstraintTokenMint(ProgramError):
+ def __init__(self):
+ super().__init__(2014, "A token mint constraint was violated")
+
+ code = 2014
+ name = "ConstraintTokenMint"
+ msg = "A token mint constraint was violated"
+
+
+class ConstraintTokenOwner(ProgramError):
+ def __init__(self):
+ super().__init__(2015, "A token owner constraint was violated")
+
+ code = 2015
+ name = "ConstraintTokenOwner"
+ msg = "A token owner constraint was violated"
+
+
+class ConstraintMintMintAuthority(ProgramError):
+ def __init__(self):
+ super().__init__(2016, "A mint mint authority constraint was violated")
+
+ code = 2016
+ name = "ConstraintMintMintAuthority"
+ msg = "A mint mint authority constraint was violated"
+
+
+class ConstraintMintFreezeAuthority(ProgramError):
+ def __init__(self):
+ super().__init__(2017, "A mint freeze authority constraint was violated")
+
+ code = 2017
+ name = "ConstraintMintFreezeAuthority"
+ msg = "A mint freeze authority constraint was violated"
+
+
+class ConstraintMintDecimals(ProgramError):
+ def __init__(self):
+ super().__init__(2018, "A mint decimals constraint was violated")
+
+ code = 2018
+ name = "ConstraintMintDecimals"
+ msg = "A mint decimals constraint was violated"
+
+
+class ConstraintSpace(ProgramError):
+ def __init__(self):
+ super().__init__(2019, "A space constraint was violated")
+
+ code = 2019
+ name = "ConstraintSpace"
+ msg = "A space constraint was violated"
+
+
+class RequireViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2500, "A require expression was violated")
+
+ code = 2500
+ name = "RequireViolated"
+ msg = "A require expression was violated"
+
+
+class RequireEqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2501, "A require_eq expression was violated")
+
+ code = 2501
+ name = "RequireEqViolated"
+ msg = "A require_eq expression was violated"
+
+
+class RequireKeysEqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2502, "A require_keys_eq expression was violated")
+
+ code = 2502
+ name = "RequireKeysEqViolated"
+ msg = "A require_keys_eq expression was violated"
+
+
+class RequireNeqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2503, "A require_neq expression was violated")
+
+ code = 2503
+ name = "RequireNeqViolated"
+ msg = "A require_neq expression was violated"
+
+
+class RequireKeysNeqViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2504, "A require_keys_neq expression was violated")
+
+ code = 2504
+ name = "RequireKeysNeqViolated"
+ msg = "A require_keys_neq expression was violated"
+
+
+class RequireGtViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2505, "A require_gt expression was violated")
+
+ code = 2505
+ name = "RequireGtViolated"
+ msg = "A require_gt expression was violated"
+
+
+class RequireGteViolated(ProgramError):
+ def __init__(self):
+ super().__init__(2506, "A require_gte expression was violated")
+
+ code = 2506
+ name = "RequireGteViolated"
+ msg = "A require_gte expression was violated"
+
+
+class AccountDiscriminatorAlreadySet(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3000, "The account discriminator was already set on this account"
+ )
+
+ code = 3000
+ name = "AccountDiscriminatorAlreadySet"
+ msg = "The account discriminator was already set on this account"
+
+
+class AccountDiscriminatorNotFound(ProgramError):
+ def __init__(self):
+ super().__init__(3001, "No 8 byte discriminator was found on the account")
+
+ code = 3001
+ name = "AccountDiscriminatorNotFound"
+ msg = "No 8 byte discriminator was found on the account"
+
+
+class AccountDiscriminatorMismatch(ProgramError):
+ def __init__(self):
+ super().__init__(3002, "8 byte discriminator did not match what was expected")
+
+ code = 3002
+ name = "AccountDiscriminatorMismatch"
+ msg = "8 byte discriminator did not match what was expected"
+
+
+class AccountDidNotDeserialize(ProgramError):
+ def __init__(self):
+ super().__init__(3003, "Failed to deserialize the account")
+
+ code = 3003
+ name = "AccountDidNotDeserialize"
+ msg = "Failed to deserialize the account"
+
+
+class AccountDidNotSerialize(ProgramError):
+ def __init__(self):
+ super().__init__(3004, "Failed to serialize the account")
+
+ code = 3004
+ name = "AccountDidNotSerialize"
+ msg = "Failed to serialize the account"
+
+
+class AccountNotEnoughKeys(ProgramError):
+ def __init__(self):
+ super().__init__(3005, "Not enough account keys given to the instruction")
+
+ code = 3005
+ name = "AccountNotEnoughKeys"
+ msg = "Not enough account keys given to the instruction"
+
+
+class AccountNotMutable(ProgramError):
+ def __init__(self):
+ super().__init__(3006, "The given account is not mutable")
+
+ code = 3006
+ name = "AccountNotMutable"
+ msg = "The given account is not mutable"
+
+
+class AccountOwnedByWrongProgram(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3007, "The given account is owned by a different program than expected"
+ )
+
+ code = 3007
+ name = "AccountOwnedByWrongProgram"
+ msg = "The given account is owned by a different program than expected"
+
+
+class InvalidProgramId(ProgramError):
+ def __init__(self):
+ super().__init__(3008, "Program ID was not as expected")
+
+ code = 3008
+ name = "InvalidProgramId"
+ msg = "Program ID was not as expected"
+
+
+class InvalidProgramExecutable(ProgramError):
+ def __init__(self):
+ super().__init__(3009, "Program account is not executable")
+
+ code = 3009
+ name = "InvalidProgramExecutable"
+ msg = "Program account is not executable"
+
+
+class AccountNotSigner(ProgramError):
+ def __init__(self):
+ super().__init__(3010, "The given account did not sign")
+
+ code = 3010
+ name = "AccountNotSigner"
+ msg = "The given account did not sign"
+
+
+class AccountNotSystemOwned(ProgramError):
+ def __init__(self):
+ super().__init__(3011, "The given account is not owned by the system program")
+
+ code = 3011
+ name = "AccountNotSystemOwned"
+ msg = "The given account is not owned by the system program"
+
+
+class AccountNotInitialized(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3012, "The program expected this account to be already initialized"
+ )
+
+ code = 3012
+ name = "AccountNotInitialized"
+ msg = "The program expected this account to be already initialized"
+
+
+class AccountNotProgramData(ProgramError):
+ def __init__(self):
+ super().__init__(3013, "The given account is not a program data account")
+
+ code = 3013
+ name = "AccountNotProgramData"
+ msg = "The given account is not a program data account"
+
+
+class AccountNotAssociatedTokenAccount(ProgramError):
+ def __init__(self):
+ super().__init__(3014, "The given account is not the associated token account")
+
+ code = 3014
+ name = "AccountNotAssociatedTokenAccount"
+ msg = "The given account is not the associated token account"
+
+
+class AccountSysvarMismatch(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 3015, "The given public key does not match the required sysvar"
+ )
+
+ code = 3015
+ name = "AccountSysvarMismatch"
+ msg = "The given public key does not match the required sysvar"
+
+
+class StateInvalidAddress(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 4000, "The given state account does not have the correct address"
+ )
+
+ code = 4000
+ name = "StateInvalidAddress"
+ msg = "The given state account does not have the correct address"
+
+
+class Deprecated(ProgramError):
+ def __init__(self):
+ super().__init__(
+ 5000, "The API being used is deprecated and should no longer be used"
+ )
+
+ code = 5000
+ name = "Deprecated"
+ msg = "The API being used is deprecated and should no longer be used"
+
+
+AnchorError = typing.Union[
+ InstructionMissing,
+ InstructionFallbackNotFound,
+ InstructionDidNotDeserialize,
+ InstructionDidNotSerialize,
+ IdlInstructionStub,
+ IdlInstructionInvalidProgram,
+ ConstraintMut,
+ ConstraintHasOne,
+ ConstraintSigner,
+ ConstraintRaw,
+ ConstraintOwner,
+ ConstraintRentExempt,
+ ConstraintSeeds,
+ ConstraintExecutable,
+ ConstraintState,
+ ConstraintAssociated,
+ ConstraintAssociatedInit,
+ ConstraintClose,
+ ConstraintAddress,
+ ConstraintZero,
+ ConstraintTokenMint,
+ ConstraintTokenOwner,
+ ConstraintMintMintAuthority,
+ ConstraintMintFreezeAuthority,
+ ConstraintMintDecimals,
+ ConstraintSpace,
+ RequireViolated,
+ RequireEqViolated,
+ RequireKeysEqViolated,
+ RequireNeqViolated,
+ RequireKeysNeqViolated,
+ RequireGtViolated,
+ RequireGteViolated,
+ AccountDiscriminatorAlreadySet,
+ AccountDiscriminatorNotFound,
+ AccountDiscriminatorMismatch,
+ AccountDidNotDeserialize,
+ AccountDidNotSerialize,
+ AccountNotEnoughKeys,
+ AccountNotMutable,
+ AccountOwnedByWrongProgram,
+ InvalidProgramId,
+ InvalidProgramExecutable,
+ AccountNotSigner,
+ AccountNotSystemOwned,
+ AccountNotInitialized,
+ AccountNotProgramData,
+ AccountNotAssociatedTokenAccount,
+ AccountSysvarMismatch,
+ StateInvalidAddress,
+ Deprecated,
+]
+ANCHOR_ERROR_MAP: dict[int, AnchorError] = {
+ 100: InstructionMissing(),
+ 101: InstructionFallbackNotFound(),
+ 102: InstructionDidNotDeserialize(),
+ 103: InstructionDidNotSerialize(),
+ 1000: IdlInstructionStub(),
+ 1001: IdlInstructionInvalidProgram(),
+ 2000: ConstraintMut(),
+ 2001: ConstraintHasOne(),
+ 2002: ConstraintSigner(),
+ 2003: ConstraintRaw(),
+ 2004: ConstraintOwner(),
+ 2005: ConstraintRentExempt(),
+ 2006: ConstraintSeeds(),
+ 2007: ConstraintExecutable(),
+ 2008: ConstraintState(),
+ 2009: ConstraintAssociated(),
+ 2010: ConstraintAssociatedInit(),
+ 2011: ConstraintClose(),
+ 2012: ConstraintAddress(),
+ 2013: ConstraintZero(),
+ 2014: ConstraintTokenMint(),
+ 2015: ConstraintTokenOwner(),
+ 2016: ConstraintMintMintAuthority(),
+ 2017: ConstraintMintFreezeAuthority(),
+ 2018: ConstraintMintDecimals(),
+ 2019: ConstraintSpace(),
+ 2500: RequireViolated(),
+ 2501: RequireEqViolated(),
+ 2502: RequireKeysEqViolated(),
+ 2503: RequireNeqViolated(),
+ 2504: RequireKeysNeqViolated(),
+ 2505: RequireGtViolated(),
+ 2506: RequireGteViolated(),
+ 3000: AccountDiscriminatorAlreadySet(),
+ 3001: AccountDiscriminatorNotFound(),
+ 3002: AccountDiscriminatorMismatch(),
+ 3003: AccountDidNotDeserialize(),
+ 3004: AccountDidNotSerialize(),
+ 3005: AccountNotEnoughKeys(),
+ 3006: AccountNotMutable(),
+ 3007: AccountOwnedByWrongProgram(),
+ 3008: InvalidProgramId(),
+ 3009: InvalidProgramExecutable(),
+ 3010: AccountNotSigner(),
+ 3011: AccountNotSystemOwned(),
+ 3012: AccountNotInitialized(),
+ 3013: AccountNotProgramData(),
+ 3014: AccountNotAssociatedTokenAccount(),
+ 3015: AccountSysvarMismatch(),
+ 4000: StateInvalidAddress(),
+ 5000: Deprecated(),
+}
+
+
+def from_code(code: int) -> typing.Optional[AnchorError]:
+ maybe_err = ANCHOR_ERROR_MAP.get(code)
+ if maybe_err is None:
+ return None
+ return maybe_err
diff --git a/basics/anchorpy-main/tests/client-gen/token/errors/custom.py b/basics/anchorpy-main/tests/client-gen/token/errors/custom.py
new file mode 100644
index 0000000..15cabe4
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/errors/custom.py
@@ -0,0 +1,239 @@
+import typing
+from anchorpy.error import ProgramError
+
+
+class NotRentExempt(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(0, "Lamport balance below rent-exempt threshold")
+
+ code = 0
+ name = "NotRentExempt"
+ msg = "Lamport balance below rent-exempt threshold"
+
+
+class InsufficientFunds(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(1, "Insufficient funds")
+
+ code = 1
+ name = "InsufficientFunds"
+ msg = "Insufficient funds"
+
+
+class InvalidMint(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(2, "Invalid Mint")
+
+ code = 2
+ name = "InvalidMint"
+ msg = "Invalid Mint"
+
+
+class MintMismatch(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(3, "Account not associated with this Mint")
+
+ code = 3
+ name = "MintMismatch"
+ msg = "Account not associated with this Mint"
+
+
+class OwnerMismatch(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(4, "Owner does not match")
+
+ code = 4
+ name = "OwnerMismatch"
+ msg = "Owner does not match"
+
+
+class FixedSupply(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(5, "Fixed supply")
+
+ code = 5
+ name = "FixedSupply"
+ msg = "Fixed supply"
+
+
+class AlreadyInUse(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(6, "Already in use")
+
+ code = 6
+ name = "AlreadyInUse"
+ msg = "Already in use"
+
+
+class InvalidNumberOfProvidedSigners(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(7, "Invalid number of provided signers")
+
+ code = 7
+ name = "InvalidNumberOfProvidedSigners"
+ msg = "Invalid number of provided signers"
+
+
+class InvalidNumberOfRequiredSigners(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(8, "Invalid number of required signers")
+
+ code = 8
+ name = "InvalidNumberOfRequiredSigners"
+ msg = "Invalid number of required signers"
+
+
+class UninitializedState(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(9, "State is unititialized")
+
+ code = 9
+ name = "UninitializedState"
+ msg = "State is unititialized"
+
+
+class NativeNotSupported(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(10, "Instruction does not support native tokens")
+
+ code = 10
+ name = "NativeNotSupported"
+ msg = "Instruction does not support native tokens"
+
+
+class NonNativeHasBalance(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(
+ 11, "Non-native account can only be closed if its balance is zero"
+ )
+
+ code = 11
+ name = "NonNativeHasBalance"
+ msg = "Non-native account can only be closed if its balance is zero"
+
+
+class InvalidInstruction(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(12, "Invalid instruction")
+
+ code = 12
+ name = "InvalidInstruction"
+ msg = "Invalid instruction"
+
+
+class InvalidState(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(13, "State is invalid for requested operation")
+
+ code = 13
+ name = "InvalidState"
+ msg = "State is invalid for requested operation"
+
+
+class Overflow(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(14, "Operation overflowed")
+
+ code = 14
+ name = "Overflow"
+ msg = "Operation overflowed"
+
+
+class AuthorityTypeNotSupported(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(15, "Account does not support specified authority type")
+
+ code = 15
+ name = "AuthorityTypeNotSupported"
+ msg = "Account does not support specified authority type"
+
+
+class MintCannotFreeze(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(16, "This token mint cannot freeze accounts")
+
+ code = 16
+ name = "MintCannotFreeze"
+ msg = "This token mint cannot freeze accounts"
+
+
+class AccountFrozen(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(17, "Account is frozen")
+
+ code = 17
+ name = "AccountFrozen"
+ msg = "Account is frozen"
+
+
+class MintDecimalsMismatch(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(
+ 18, "The provided decimals value different from the Mint decimals"
+ )
+
+ code = 18
+ name = "MintDecimalsMismatch"
+ msg = "The provided decimals value different from the Mint decimals"
+
+
+class NonNativeNotSupported(ProgramError):
+ def __init__(self) -> None:
+ super().__init__(19, "Instruction does not support non-native tokens")
+
+ code = 19
+ name = "NonNativeNotSupported"
+ msg = "Instruction does not support non-native tokens"
+
+
+CustomError = typing.Union[
+ NotRentExempt,
+ InsufficientFunds,
+ InvalidMint,
+ MintMismatch,
+ OwnerMismatch,
+ FixedSupply,
+ AlreadyInUse,
+ InvalidNumberOfProvidedSigners,
+ InvalidNumberOfRequiredSigners,
+ UninitializedState,
+ NativeNotSupported,
+ NonNativeHasBalance,
+ InvalidInstruction,
+ InvalidState,
+ Overflow,
+ AuthorityTypeNotSupported,
+ MintCannotFreeze,
+ AccountFrozen,
+ MintDecimalsMismatch,
+ NonNativeNotSupported,
+]
+CUSTOM_ERROR_MAP: dict[int, CustomError] = {
+ 0: NotRentExempt(),
+ 1: InsufficientFunds(),
+ 2: InvalidMint(),
+ 3: MintMismatch(),
+ 4: OwnerMismatch(),
+ 5: FixedSupply(),
+ 6: AlreadyInUse(),
+ 7: InvalidNumberOfProvidedSigners(),
+ 8: InvalidNumberOfRequiredSigners(),
+ 9: UninitializedState(),
+ 10: NativeNotSupported(),
+ 11: NonNativeHasBalance(),
+ 12: InvalidInstruction(),
+ 13: InvalidState(),
+ 14: Overflow(),
+ 15: AuthorityTypeNotSupported(),
+ 16: MintCannotFreeze(),
+ 17: AccountFrozen(),
+ 18: MintDecimalsMismatch(),
+ 19: NonNativeNotSupported(),
+}
+
+
+def from_code(code: int) -> typing.Optional[CustomError]:
+ maybe_err = CUSTOM_ERROR_MAP.get(code)
+ if maybe_err is None:
+ return None
+ return maybe_err
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/__init__.py b/basics/anchorpy-main/tests/client-gen/token/instructions/__init__.py
new file mode 100644
index 0000000..7167c3b
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/__init__.py
@@ -0,0 +1,60 @@
+from .initialize_mint import initialize_mint, InitializeMintArgs, InitializeMintAccounts
+from .initialize_account import initialize_account, InitializeAccountAccounts
+from .initialize_multisig import (
+ initialize_multisig,
+ InitializeMultisigArgs,
+ InitializeMultisigAccounts,
+)
+from .transfer import transfer, TransferArgs, TransferAccounts
+from .approve import approve, ApproveArgs, ApproveAccounts
+from .revoke import revoke, RevokeAccounts
+from .set_authority import set_authority, SetAuthorityArgs, SetAuthorityAccounts
+from .mint_to import mint_to, MintToArgs, MintToAccounts
+from .burn import burn, BurnArgs, BurnAccounts
+from .close_account import close_account, CloseAccountAccounts
+from .freeze_account import freeze_account, FreezeAccountAccounts
+from .thaw_account import thaw_account, ThawAccountAccounts
+from .transfer_checked import (
+ transfer_checked,
+ TransferCheckedArgs,
+ TransferCheckedAccounts,
+)
+from .approve_checked import approve_checked, ApproveCheckedArgs, ApproveCheckedAccounts
+from .mint_to_checked import mint_to_checked, MintToCheckedArgs, MintToCheckedAccounts
+from .burn_checked import burn_checked, BurnCheckedArgs, BurnCheckedAccounts
+from .initialize_account2 import (
+ initialize_account2,
+ InitializeAccount2Args,
+ InitializeAccount2Accounts,
+)
+from .sync_native import sync_native, SyncNativeAccounts
+from .initialize_account3 import (
+ initialize_account3,
+ InitializeAccount3Args,
+ InitializeAccount3Accounts,
+)
+from .initialize_multisig2 import (
+ initialize_multisig2,
+ InitializeMultisig2Args,
+ InitializeMultisig2Accounts,
+)
+from .initialize_mint2 import (
+ initialize_mint2,
+ InitializeMint2Args,
+ InitializeMint2Accounts,
+)
+from .get_account_data_size import get_account_data_size, GetAccountDataSizeAccounts
+from .initialize_immutable_owner import (
+ initialize_immutable_owner,
+ InitializeImmutableOwnerAccounts,
+)
+from .amount_to_ui_amount import (
+ amount_to_ui_amount,
+ AmountToUiAmountArgs,
+ AmountToUiAmountAccounts,
+)
+from .ui_amount_to_amount import (
+ ui_amount_to_amount,
+ UiAmountToAmountArgs,
+ UiAmountToAmountAccounts,
+)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/amount_to_ui_amount.py b/basics/anchorpy-main/tests/client-gen/token/instructions/amount_to_ui_amount.py
new file mode 100644
index 0000000..a19f397
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/amount_to_ui_amount.py
@@ -0,0 +1,38 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class AmountToUiAmountArgs(typing.TypedDict):
+ amount: int
+
+
+layout = borsh.CStruct("amount" / borsh.U64)
+
+
+class AmountToUiAmountAccounts(typing.TypedDict):
+ mint: Pubkey
+
+
+def amount_to_ui_amount(
+ args: AmountToUiAmountArgs,
+ accounts: AmountToUiAmountAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False)
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xa0\x91\xc8b\xf2\x9c\x1eZ"
+ encoded_args = layout.build(
+ {
+ "amount": args["amount"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/approve.py b/basics/anchorpy-main/tests/client-gen/token/instructions/approve.py
new file mode 100644
index 0000000..2916385
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/approve.py
@@ -0,0 +1,42 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class ApproveArgs(typing.TypedDict):
+ amount: int
+
+
+layout = borsh.CStruct("amount" / borsh.U64)
+
+
+class ApproveAccounts(typing.TypedDict):
+ source: Pubkey
+ delegate: Pubkey
+ owner: Pubkey
+
+
+def approve(
+ args: ApproveArgs,
+ accounts: ApproveAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["source"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["delegate"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["owner"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"EJ\xd9$suaL"
+ encoded_args = layout.build(
+ {
+ "amount": args["amount"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/approve_checked.py b/basics/anchorpy-main/tests/client-gen/token/instructions/approve_checked.py
new file mode 100644
index 0000000..b734d0a
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/approve_checked.py
@@ -0,0 +1,46 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class ApproveCheckedArgs(typing.TypedDict):
+ amount: int
+ decimals: int
+
+
+layout = borsh.CStruct("amount" / borsh.U64, "decimals" / borsh.U8)
+
+
+class ApproveCheckedAccounts(typing.TypedDict):
+ source: Pubkey
+ mint: Pubkey
+ delegate: Pubkey
+ owner: Pubkey
+
+
+def approve_checked(
+ args: ApproveCheckedArgs,
+ accounts: ApproveCheckedAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["source"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["delegate"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["owner"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"/\xc5\xfe*:\xc9:m"
+ encoded_args = layout.build(
+ {
+ "amount": args["amount"],
+ "decimals": args["decimals"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/burn.py b/basics/anchorpy-main/tests/client-gen/token/instructions/burn.py
new file mode 100644
index 0000000..be55863
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/burn.py
@@ -0,0 +1,42 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class BurnArgs(typing.TypedDict):
+ amount: int
+
+
+layout = borsh.CStruct("amount" / borsh.U64)
+
+
+class BurnAccounts(typing.TypedDict):
+ account: Pubkey
+ mint: Pubkey
+ authority: Pubkey
+
+
+def burn(
+ args: BurnArgs,
+ accounts: BurnAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["authority"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"tn\x1d8k\xdb*]"
+ encoded_args = layout.build(
+ {
+ "amount": args["amount"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/burn_checked.py b/basics/anchorpy-main/tests/client-gen/token/instructions/burn_checked.py
new file mode 100644
index 0000000..913224a
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/burn_checked.py
@@ -0,0 +1,44 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class BurnCheckedArgs(typing.TypedDict):
+ amount: int
+ decimals: int
+
+
+layout = borsh.CStruct("amount" / borsh.U64, "decimals" / borsh.U8)
+
+
+class BurnCheckedAccounts(typing.TypedDict):
+ account: Pubkey
+ mint: Pubkey
+ authority: Pubkey
+
+
+def burn_checked(
+ args: BurnCheckedArgs,
+ accounts: BurnCheckedAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["authority"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xc6y\xc8fx\xd0\x9b\xb2"
+ encoded_args = layout.build(
+ {
+ "amount": args["amount"],
+ "decimals": args["decimals"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/close_account.py b/basics/anchorpy-main/tests/client-gen/token/instructions/close_account.py
new file mode 100644
index 0000000..c6bf6de
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/close_account.py
@@ -0,0 +1,29 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class CloseAccountAccounts(typing.TypedDict):
+ account: Pubkey
+ destination: Pubkey
+ owner: Pubkey
+
+
+def close_account(
+ accounts: CloseAccountAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["destination"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["owner"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b'}\xff\x95\x0en"H\x18'
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/freeze_account.py b/basics/anchorpy-main/tests/client-gen/token/instructions/freeze_account.py
new file mode 100644
index 0000000..921cded
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/freeze_account.py
@@ -0,0 +1,29 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class FreezeAccountAccounts(typing.TypedDict):
+ account: Pubkey
+ mint: Pubkey
+ owner: Pubkey
+
+
+def freeze_account(
+ accounts: FreezeAccountAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["owner"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xfdKR\x85\xa7\xee+\x82"
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/get_account_data_size.py b/basics/anchorpy-main/tests/client-gen/token/instructions/get_account_data_size.py
new file mode 100644
index 0000000..f5a55f4
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/get_account_data_size.py
@@ -0,0 +1,25 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class GetAccountDataSizeAccounts(typing.TypedDict):
+ mint: Pubkey
+
+
+def get_account_data_size(
+ accounts: GetAccountDataSizeAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False)
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\x10\xb1\xd2\x80\x15-o\x1f"
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_account.py b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_account.py
new file mode 100644
index 0000000..288bef6
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_account.py
@@ -0,0 +1,31 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.sysvar import RENT
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class InitializeAccountAccounts(typing.TypedDict):
+ account: Pubkey
+ mint: Pubkey
+ owner: Pubkey
+
+
+def initialize_account(
+ accounts: InitializeAccountAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["owner"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=RENT, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"Jsc]\xc5Eg\x07"
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_account2.py b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_account2.py
new file mode 100644
index 0000000..b3257fb
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_account2.py
@@ -0,0 +1,43 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.sysvar import RENT
+from solders.instruction import Instruction, AccountMeta
+from anchorpy.borsh_extension import BorshPubkey
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class InitializeAccount2Args(typing.TypedDict):
+ owner: Pubkey
+
+
+layout = borsh.CStruct("owner" / BorshPubkey)
+
+
+class InitializeAccount2Accounts(typing.TypedDict):
+ account: Pubkey
+ mint: Pubkey
+
+
+def initialize_account2(
+ args: InitializeAccount2Args,
+ accounts: InitializeAccount2Accounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=RENT, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\x08\xb6\x95\x90\xb9\x1f\xd1i"
+ encoded_args = layout.build(
+ {
+ "owner": args["owner"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_account3.py b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_account3.py
new file mode 100644
index 0000000..83427fb
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_account3.py
@@ -0,0 +1,41 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from anchorpy.borsh_extension import BorshPubkey
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class InitializeAccount3Args(typing.TypedDict):
+ owner: Pubkey
+
+
+layout = borsh.CStruct("owner" / BorshPubkey)
+
+
+class InitializeAccount3Accounts(typing.TypedDict):
+ account: Pubkey
+ mint: Pubkey
+
+
+def initialize_account3(
+ args: InitializeAccount3Args,
+ accounts: InitializeAccount3Accounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\x17\x8e\x8c\x87\x15\xa0\x85@"
+ encoded_args = layout.build(
+ {
+ "owner": args["owner"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_immutable_owner.py b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_immutable_owner.py
new file mode 100644
index 0000000..ffea985
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_immutable_owner.py
@@ -0,0 +1,25 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class InitializeImmutableOwnerAccounts(typing.TypedDict):
+ account: Pubkey
+
+
+def initialize_immutable_owner(
+ accounts: InitializeImmutableOwnerAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True)
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b'\x8d2\x0f,\xc3\xf7"<'
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_mint.py b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_mint.py
new file mode 100644
index 0000000..c2b94af
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_mint.py
@@ -0,0 +1,49 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.sysvar import RENT
+from solders.instruction import Instruction, AccountMeta
+from anchorpy.borsh_extension import BorshPubkey, COption
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class InitializeMintArgs(typing.TypedDict):
+ decimals: int
+ mint_authority: Pubkey
+ freeze_authority: typing.Optional[Pubkey]
+
+
+layout = borsh.CStruct(
+ "decimals" / borsh.U8,
+ "mint_authority" / BorshPubkey,
+ "freeze_authority" / COption(BorshPubkey),
+)
+
+
+class InitializeMintAccounts(typing.TypedDict):
+ mint: Pubkey
+
+
+def initialize_mint(
+ args: InitializeMintArgs,
+ accounts: InitializeMintAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=RENT, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xd1*\xc3\x04\x81U\xd1,"
+ encoded_args = layout.build(
+ {
+ "decimals": args["decimals"],
+ "mint_authority": args["mint_authority"],
+ "freeze_authority": args["freeze_authority"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_mint2.py b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_mint2.py
new file mode 100644
index 0000000..ef12ee6
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_mint2.py
@@ -0,0 +1,47 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from anchorpy.borsh_extension import BorshPubkey, COption
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class InitializeMint2Args(typing.TypedDict):
+ decimals: int
+ mint_authority: Pubkey
+ freeze_authority: typing.Optional[Pubkey]
+
+
+layout = borsh.CStruct(
+ "decimals" / borsh.U8,
+ "mint_authority" / BorshPubkey,
+ "freeze_authority" / COption(BorshPubkey),
+)
+
+
+class InitializeMint2Accounts(typing.TypedDict):
+ mint: Pubkey
+
+
+def initialize_mint2(
+ args: InitializeMint2Args,
+ accounts: InitializeMint2Accounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=True)
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"_l\xc6\xd2H\xf3\x8f\xeb"
+ encoded_args = layout.build(
+ {
+ "decimals": args["decimals"],
+ "mint_authority": args["mint_authority"],
+ "freeze_authority": args["freeze_authority"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_multisig.py b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_multisig.py
new file mode 100644
index 0000000..e5a7374
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_multisig.py
@@ -0,0 +1,40 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.sysvar import RENT
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class InitializeMultisigArgs(typing.TypedDict):
+ m: int
+
+
+layout = borsh.CStruct("m" / borsh.U8)
+
+
+class InitializeMultisigAccounts(typing.TypedDict):
+ multisig: Pubkey
+
+
+def initialize_multisig(
+ args: InitializeMultisigArgs,
+ accounts: InitializeMultisigAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["multisig"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=RENT, is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xdc\x82u\x15\x1b\xe3N\xd5"
+ encoded_args = layout.build(
+ {
+ "m": args["m"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_multisig2.py b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_multisig2.py
new file mode 100644
index 0000000..2d77574
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/initialize_multisig2.py
@@ -0,0 +1,40 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class InitializeMultisig2Args(typing.TypedDict):
+ m: int
+
+
+layout = borsh.CStruct("m" / borsh.U8)
+
+
+class InitializeMultisig2Accounts(typing.TypedDict):
+ multisig: Pubkey
+ signer: Pubkey
+
+
+def initialize_multisig2(
+ args: InitializeMultisig2Args,
+ accounts: InitializeMultisig2Accounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["multisig"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["signer"], is_signer=False, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"Q\xefI'\x1b\x94\x02\x92"
+ encoded_args = layout.build(
+ {
+ "m": args["m"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/mint_to.py b/basics/anchorpy-main/tests/client-gen/token/instructions/mint_to.py
new file mode 100644
index 0000000..947566c
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/mint_to.py
@@ -0,0 +1,42 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class MintToArgs(typing.TypedDict):
+ amount: int
+
+
+layout = borsh.CStruct("amount" / borsh.U64)
+
+
+class MintToAccounts(typing.TypedDict):
+ mint: Pubkey
+ account: Pubkey
+ owner: Pubkey
+
+
+def mint_to(
+ args: MintToArgs,
+ accounts: MintToAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["owner"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b'\xf1"0\xba%\xb3{\xc0'
+ encoded_args = layout.build(
+ {
+ "amount": args["amount"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/mint_to_checked.py b/basics/anchorpy-main/tests/client-gen/token/instructions/mint_to_checked.py
new file mode 100644
index 0000000..f4ba48c
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/mint_to_checked.py
@@ -0,0 +1,44 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class MintToCheckedArgs(typing.TypedDict):
+ amount: int
+ decimals: int
+
+
+layout = borsh.CStruct("amount" / borsh.U64, "decimals" / borsh.U8)
+
+
+class MintToCheckedAccounts(typing.TypedDict):
+ mint: Pubkey
+ account: Pubkey
+ owner: Pubkey
+
+
+def mint_to_checked(
+ args: MintToCheckedArgs,
+ accounts: MintToCheckedAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["owner"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xe5\xec$\xf0v\xe1-}"
+ encoded_args = layout.build(
+ {
+ "amount": args["amount"],
+ "decimals": args["decimals"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/revoke.py b/basics/anchorpy-main/tests/client-gen/token/instructions/revoke.py
new file mode 100644
index 0000000..54009f8
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/revoke.py
@@ -0,0 +1,27 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class RevokeAccounts(typing.TypedDict):
+ source: Pubkey
+ owner: Pubkey
+
+
+def revoke(
+ accounts: RevokeAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["source"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["owner"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b'\xaa\x17\x1f"\x85\xad]\xf2'
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/set_authority.py b/basics/anchorpy-main/tests/client-gen/token/instructions/set_authority.py
new file mode 100644
index 0000000..51ad91c
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/set_authority.py
@@ -0,0 +1,49 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from anchorpy.borsh_extension import BorshPubkey, COption
+import borsh_construct as borsh
+from .. import types
+from ..program_id import PROGRAM_ID
+
+
+class SetAuthorityArgs(typing.TypedDict):
+ authority_type: types.authority_type.AuthorityTypeKind
+ new_authority: typing.Optional[Pubkey]
+
+
+layout = borsh.CStruct(
+ "authority_type" / types.authority_type.layout,
+ "new_authority" / COption(BorshPubkey),
+)
+
+
+class SetAuthorityAccounts(typing.TypedDict):
+ owned: Pubkey
+ owner: Pubkey
+ signer: Pubkey
+
+
+def set_authority(
+ args: SetAuthorityArgs,
+ accounts: SetAuthorityAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["owned"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["owner"], is_signer=True, is_writable=False),
+ AccountMeta(pubkey=accounts["signer"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\x85\xfa%\x15n\xa3\x1ay"
+ encoded_args = layout.build(
+ {
+ "authority_type": args["authority_type"].to_encodable(),
+ "new_authority": args["new_authority"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/sync_native.py b/basics/anchorpy-main/tests/client-gen/token/instructions/sync_native.py
new file mode 100644
index 0000000..d615229
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/sync_native.py
@@ -0,0 +1,25 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class SyncNativeAccounts(typing.TypedDict):
+ account: Pubkey
+
+
+def sync_native(
+ accounts: SyncNativeAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True)
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\x9b\xdb$$\xef\x80\x15A"
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/thaw_account.py b/basics/anchorpy-main/tests/client-gen/token/instructions/thaw_account.py
new file mode 100644
index 0000000..fab2d9c
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/thaw_account.py
@@ -0,0 +1,29 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+from ..program_id import PROGRAM_ID
+
+
+class ThawAccountAccounts(typing.TypedDict):
+ account: Pubkey
+ mint: Pubkey
+ owner: Pubkey
+
+
+def thaw_account(
+ accounts: ThawAccountAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["account"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["owner"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"s\x98O\xd5\xd5\xa9\xb8#"
+ encoded_args = b""
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/transfer.py b/basics/anchorpy-main/tests/client-gen/token/instructions/transfer.py
new file mode 100644
index 0000000..a24edfb
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/transfer.py
@@ -0,0 +1,42 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class TransferArgs(typing.TypedDict):
+ amount: int
+
+
+layout = borsh.CStruct("amount" / borsh.U64)
+
+
+class TransferAccounts(typing.TypedDict):
+ source: Pubkey
+ destination: Pubkey
+ authority: Pubkey
+
+
+def transfer(
+ args: TransferArgs,
+ accounts: TransferAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["source"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["destination"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["authority"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xa34\xc8\xe7\x8c\x03E\xba"
+ encoded_args = layout.build(
+ {
+ "amount": args["amount"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/transfer_checked.py b/basics/anchorpy-main/tests/client-gen/token/instructions/transfer_checked.py
new file mode 100644
index 0000000..429e631
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/transfer_checked.py
@@ -0,0 +1,46 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class TransferCheckedArgs(typing.TypedDict):
+ amount: int
+ decimals: int
+
+
+layout = borsh.CStruct("amount" / borsh.U64, "decimals" / borsh.U8)
+
+
+class TransferCheckedAccounts(typing.TypedDict):
+ source: Pubkey
+ mint: Pubkey
+ destination: Pubkey
+ authority: Pubkey
+
+
+def transfer_checked(
+ args: TransferCheckedArgs,
+ accounts: TransferCheckedAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["source"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False),
+ AccountMeta(pubkey=accounts["destination"], is_signer=False, is_writable=True),
+ AccountMeta(pubkey=accounts["authority"], is_signer=True, is_writable=False),
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"w\xfa\xca\x18\xfd\x87\xf4y"
+ encoded_args = layout.build(
+ {
+ "amount": args["amount"],
+ "decimals": args["decimals"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/instructions/ui_amount_to_amount.py b/basics/anchorpy-main/tests/client-gen/token/instructions/ui_amount_to_amount.py
new file mode 100644
index 0000000..bc72ac8
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/instructions/ui_amount_to_amount.py
@@ -0,0 +1,38 @@
+from __future__ import annotations
+import typing
+from solders.pubkey import Pubkey
+from solders.instruction import Instruction, AccountMeta
+import borsh_construct as borsh
+from ..program_id import PROGRAM_ID
+
+
+class UiAmountToAmountArgs(typing.TypedDict):
+ ui_amount: str
+
+
+layout = borsh.CStruct(borsh.String)
+
+
+class UiAmountToAmountAccounts(typing.TypedDict):
+ mint: Pubkey
+
+
+def ui_amount_to_amount(
+ args: UiAmountToAmountArgs,
+ accounts: UiAmountToAmountAccounts,
+ program_id: Pubkey = PROGRAM_ID,
+ remaining_accounts: typing.Optional[typing.List[AccountMeta]] = None,
+) -> Instruction:
+ keys: list[AccountMeta] = [
+ AccountMeta(pubkey=accounts["mint"], is_signer=False, is_writable=False)
+ ]
+ if remaining_accounts is not None:
+ keys += remaining_accounts
+ identifier = b"\xad\xf3@\x04g\x1f84"
+ encoded_args = layout.build(
+ {
+ "ui_amount": args["ui_amount"],
+ }
+ )
+ data = identifier + encoded_args
+ return Instruction(program_id, data, keys)
diff --git a/basics/anchorpy-main/tests/client-gen/token/program_id.py b/basics/anchorpy-main/tests/client-gen/token/program_id.py
new file mode 100644
index 0000000..6f3e9ff
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/program_id.py
@@ -0,0 +1,3 @@
+from solders.pubkey import Pubkey
+
+PROGRAM_ID = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
diff --git a/basics/anchorpy-main/tests/client-gen/token/types/__init__.py b/basics/anchorpy-main/tests/client-gen/token/types/__init__.py
new file mode 100644
index 0000000..a0a21a6
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/types/__init__.py
@@ -0,0 +1,5 @@
+import typing
+from . import account_state
+from .account_state import AccountStateKind, AccountStateJSON
+from . import authority_type
+from .authority_type import AuthorityTypeKind, AuthorityTypeJSON
diff --git a/basics/anchorpy-main/tests/client-gen/token/types/account_state.py b/basics/anchorpy-main/tests/client-gen/token/types/account_state.py
new file mode 100644
index 0000000..29e8464
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/types/account_state.py
@@ -0,0 +1,105 @@
+from __future__ import annotations
+import typing
+from dataclasses import dataclass
+from anchorpy.borsh_extension import EnumForCodegen
+import borsh_construct as borsh
+
+
+class UninitializedJSON(typing.TypedDict):
+ kind: typing.Literal["Uninitialized"]
+
+
+class InitializedJSON(typing.TypedDict):
+ kind: typing.Literal["Initialized"]
+
+
+class FrozenJSON(typing.TypedDict):
+ kind: typing.Literal["Frozen"]
+
+
+@dataclass
+class Uninitialized:
+ discriminator: typing.ClassVar = 0
+ kind: typing.ClassVar = "Uninitialized"
+
+ @classmethod
+ def to_json(cls) -> UninitializedJSON:
+ return UninitializedJSON(
+ kind="Uninitialized",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "Uninitialized": {},
+ }
+
+
+@dataclass
+class Initialized:
+ discriminator: typing.ClassVar = 1
+ kind: typing.ClassVar = "Initialized"
+
+ @classmethod
+ def to_json(cls) -> InitializedJSON:
+ return InitializedJSON(
+ kind="Initialized",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "Initialized": {},
+ }
+
+
+@dataclass
+class Frozen:
+ discriminator: typing.ClassVar = 2
+ kind: typing.ClassVar = "Frozen"
+
+ @classmethod
+ def to_json(cls) -> FrozenJSON:
+ return FrozenJSON(
+ kind="Frozen",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "Frozen": {},
+ }
+
+
+AccountStateKind = typing.Union[Uninitialized, Initialized, Frozen]
+AccountStateJSON = typing.Union[UninitializedJSON, InitializedJSON, FrozenJSON]
+
+
+def from_decoded(obj: dict) -> AccountStateKind:
+ if not isinstance(obj, dict):
+ raise ValueError("Invalid enum object")
+ if "Uninitialized" in obj:
+ return Uninitialized()
+ if "Initialized" in obj:
+ return Initialized()
+ if "Frozen" in obj:
+ return Frozen()
+ raise ValueError("Invalid enum object")
+
+
+def from_json(obj: AccountStateJSON) -> AccountStateKind:
+ if obj["kind"] == "Uninitialized":
+ return Uninitialized()
+ if obj["kind"] == "Initialized":
+ return Initialized()
+ if obj["kind"] == "Frozen":
+ return Frozen()
+ kind = obj["kind"]
+ raise ValueError(f"Unrecognized enum kind: {kind}")
+
+
+layout = EnumForCodegen(
+ "Uninitialized" / borsh.CStruct(),
+ "Initialized" / borsh.CStruct(),
+ "Frozen" / borsh.CStruct(),
+)
diff --git a/basics/anchorpy-main/tests/client-gen/token/types/authority_type.py b/basics/anchorpy-main/tests/client-gen/token/types/authority_type.py
new file mode 100644
index 0000000..b77138e
--- /dev/null
+++ b/basics/anchorpy-main/tests/client-gen/token/types/authority_type.py
@@ -0,0 +1,134 @@
+from __future__ import annotations
+import typing
+from dataclasses import dataclass
+from anchorpy.borsh_extension import EnumForCodegen
+import borsh_construct as borsh
+
+
+class MintTokensJSON(typing.TypedDict):
+ kind: typing.Literal["MintTokens"]
+
+
+class FreezeAccountJSON(typing.TypedDict):
+ kind: typing.Literal["FreezeAccount"]
+
+
+class AccountOwnerJSON(typing.TypedDict):
+ kind: typing.Literal["AccountOwner"]
+
+
+class CloseAccountJSON(typing.TypedDict):
+ kind: typing.Literal["CloseAccount"]
+
+
+@dataclass
+class MintTokens:
+ discriminator: typing.ClassVar = 0
+ kind: typing.ClassVar = "MintTokens"
+
+ @classmethod
+ def to_json(cls) -> MintTokensJSON:
+ return MintTokensJSON(
+ kind="MintTokens",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "MintTokens": {},
+ }
+
+
+@dataclass
+class FreezeAccount:
+ discriminator: typing.ClassVar = 1
+ kind: typing.ClassVar = "FreezeAccount"
+
+ @classmethod
+ def to_json(cls) -> FreezeAccountJSON:
+ return FreezeAccountJSON(
+ kind="FreezeAccount",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "FreezeAccount": {},
+ }
+
+
+@dataclass
+class AccountOwner:
+ discriminator: typing.ClassVar = 2
+ kind: typing.ClassVar = "AccountOwner"
+
+ @classmethod
+ def to_json(cls) -> AccountOwnerJSON:
+ return AccountOwnerJSON(
+ kind="AccountOwner",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "AccountOwner": {},
+ }
+
+
+@dataclass
+class CloseAccount:
+ discriminator: typing.ClassVar = 3
+ kind: typing.ClassVar = "CloseAccount"
+
+ @classmethod
+ def to_json(cls) -> CloseAccountJSON:
+ return CloseAccountJSON(
+ kind="CloseAccount",
+ )
+
+ @classmethod
+ def to_encodable(cls) -> dict:
+ return {
+ "CloseAccount": {},
+ }
+
+
+AuthorityTypeKind = typing.Union[MintTokens, FreezeAccount, AccountOwner, CloseAccount]
+AuthorityTypeJSON = typing.Union[
+ MintTokensJSON, FreezeAccountJSON, AccountOwnerJSON, CloseAccountJSON
+]
+
+
+def from_decoded(obj: dict) -> AuthorityTypeKind:
+ if not isinstance(obj, dict):
+ raise ValueError("Invalid enum object")
+ if "MintTokens" in obj:
+ return MintTokens()
+ if "FreezeAccount" in obj:
+ return FreezeAccount()
+ if "AccountOwner" in obj:
+ return AccountOwner()
+ if "CloseAccount" in obj:
+ return CloseAccount()
+ raise ValueError("Invalid enum object")
+
+
+def from_json(obj: AuthorityTypeJSON) -> AuthorityTypeKind:
+ if obj["kind"] == "MintTokens":
+ return MintTokens()
+ if obj["kind"] == "FreezeAccount":
+ return FreezeAccount()
+ if obj["kind"] == "AccountOwner":
+ return AccountOwner()
+ if obj["kind"] == "CloseAccount":
+ return CloseAccount()
+ kind = obj["kind"]
+ raise ValueError(f"Unrecognized enum kind: {kind}")
+
+
+layout = EnumForCodegen(
+ "MintTokens" / borsh.CStruct(),
+ "FreezeAccount" / borsh.CStruct(),
+ "AccountOwner" / borsh.CStruct(),
+ "CloseAccount" / borsh.CStruct(),
+)
diff --git a/basics/anchorpy-main/tests/conftest.py b/basics/anchorpy-main/tests/conftest.py
new file mode 100644
index 0000000..7030338
--- /dev/null
+++ b/basics/anchorpy-main/tests/conftest.py
@@ -0,0 +1,38 @@
+"""Pytest config."""
+import asyncio
+import subprocess
+from pathlib import Path
+
+from pytest import fixture
+
+# Since our other fixtures have module scope, we need to define
+# this event_loop fixture and give it module scope otherwise
+# pytest-asyncio will break.
+
+
+@fixture(scope="module")
+def event_loop():
+ """Create an instance of the default event loop for each test case."""
+ loop = asyncio.get_event_loop_policy().new_event_loop()
+ yield loop
+ loop.close()
+
+
+@fixture(scope="session")
+def project_parent_dir(tmpdir_factory) -> Path:
+ return Path(tmpdir_factory.mktemp("temp"))
+
+
+@fixture(scope="session")
+def project_dir(project_parent_dir: Path) -> Path:
+ proj_dir = project_parent_dir / "tmp"
+ command = (
+ f"anchorpy client-gen tests/idls/clientgen_example_program.json {proj_dir} "
+ "--program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 --pdas"
+ )
+ subprocess.run(
+ command,
+ shell=True,
+ check=True,
+ )
+ return proj_dir
diff --git a/basics/anchorpy-main/tests/idls/basic_0.json b/basics/anchorpy-main/tests/idls/basic_0.json
new file mode 100644
index 0000000..6eb8507
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/basic_0.json
@@ -0,0 +1,14 @@
+{
+ "version": "0.0.0",
+ "name": "basic_0",
+ "instructions": [
+ {
+ "name": "initialize",
+ "accounts": [],
+ "args": []
+ }
+ ],
+ "metadata": {
+ "address": "8nA4T4UFdYz1sKuEFdnj2mYcJ6hp79Tw14sPvTQVWwVb"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/basic_1.json b/basics/anchorpy-main/tests/idls/basic_1.json
new file mode 100644
index 0000000..810ed34
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/basic_1.json
@@ -0,0 +1,57 @@
+{
+ "version": "0.0.0",
+ "name": "basic_1",
+ "instructions": [
+ {
+ "name": "initialize",
+ "accounts": [
+ {
+ "name": "myAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "update",
+ "accounts": [
+ {
+ "name": "myAccount",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "MyAccount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/basic_2.json b/basics/anchorpy-main/tests/idls/basic_2.json
new file mode 100644
index 0000000..7777c45
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/basic_2.json
@@ -0,0 +1,64 @@
+{
+ "version": "0.0.0",
+ "name": "basic_2",
+ "instructions": [
+ {
+ "name": "create",
+ "accounts": [
+ {
+ "name": "counter",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "authority",
+ "type": "publicKey"
+ }
+ ]
+ },
+ {
+ "name": "increment",
+ "accounts": [
+ {
+ "name": "counter",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Counter",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "count",
+ "type": "u64"
+ }
+ ]
+ }
+ }
+ ],
+ "metadata": {
+ "address": "4V6T2muqU1mHSg5XfK3SMgxZWQRSEUh72LzwGTLHGzsY"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/basic_5.json b/basics/anchorpy-main/tests/idls/basic_5.json
new file mode 100644
index 0000000..ecde024
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/basic_5.json
@@ -0,0 +1,80 @@
+{
+ "version": "0.0.0",
+ "name": "basic_5",
+ "instructions": [
+ {
+ "name": "createMint",
+ "accounts": [
+ {
+ "name": "mint",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "createToken",
+ "accounts": [
+ {
+ "name": "token",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Mint",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "supply",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Token",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "amount",
+ "type": "u32"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "mint",
+ "type": "publicKey"
+ }
+ ]
+ }
+ }
+ ],
+ "metadata": {
+ "address": "99cGumFqPFhCLTUxs9BoyhXAV6c19Ca44BYZVn6KG1Pu"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/candy_machine.json b/basics/anchorpy-main/tests/idls/candy_machine.json
new file mode 100644
index 0000000..dcae308
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/candy_machine.json
@@ -0,0 +1,915 @@
+{
+ "version": "4.0.2",
+ "name": "candy_machine",
+ "instructions": [
+ {
+ "name": "initializeCandyMachine",
+ "accounts": [
+ {
+ "name": "candyMachine",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "wallet",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "data",
+ "type": {
+ "defined": "CandyMachineData"
+ }
+ }
+ ]
+ },
+ {
+ "name": "updateCandyMachine",
+ "accounts": [
+ {
+ "name": "candyMachine",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "wallet",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "data",
+ "type": {
+ "defined": "CandyMachineData"
+ }
+ }
+ ]
+ },
+ {
+ "name": "updateAuthority",
+ "accounts": [
+ {
+ "name": "candyMachine",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "wallet",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "newAuthority",
+ "type": {
+ "option": "publicKey"
+ }
+ }
+ ]
+ },
+ {
+ "name": "addConfigLines",
+ "accounts": [
+ {
+ "name": "candyMachine",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "index",
+ "type": "u32"
+ },
+ {
+ "name": "configLines",
+ "type": {
+ "vec": {
+ "defined": "ConfigLine"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "setCollection",
+ "accounts": [
+ {
+ "name": "candyMachine",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "collectionPda",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "metadata",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "edition",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "collectionAuthorityRecord",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenMetadataProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "removeCollection",
+ "accounts": [
+ {
+ "name": "candyMachine",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "collectionPda",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "metadata",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "collectionAuthorityRecord",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenMetadataProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "mintNft",
+ "accounts": [
+ {
+ "name": "candyMachine",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "candyMachineCreator",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "wallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "metadata",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mintAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "updateAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "masterEdition",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenMetadataProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false,
+ "docs": [
+ "Account not actually used."
+ ]
+ },
+ {
+ "name": "recentBlockhashes",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "instructionSysvarAccount",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "creatorBump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "setCollectionDuringMint",
+ "accounts": [
+ {
+ "name": "candyMachine",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "metadata",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "collectionPda",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenMetadataProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "instructions",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "collectionMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "collectionMetadata",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "collectionMasterEdition",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "collectionAuthorityRecord",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "withdrawFunds",
+ "accounts": [
+ {
+ "name": "candyMachine",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "CandyMachine",
+ "docs": [
+ "Candy machine state and config data."
+ ],
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "wallet",
+ "type": "publicKey"
+ },
+ {
+ "name": "tokenMint",
+ "type": {
+ "option": "publicKey"
+ }
+ },
+ {
+ "name": "itemsRedeemed",
+ "type": "u64"
+ },
+ {
+ "name": "data",
+ "type": {
+ "defined": "CandyMachineData"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "CollectionPDA",
+ "docs": [
+ "Collection PDA account"
+ ],
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "mint",
+ "type": "publicKey"
+ },
+ {
+ "name": "candyMachine",
+ "type": "publicKey"
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "CandyMachineData",
+ "docs": [
+ "Candy machine settings data."
+ ],
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "uuid",
+ "type": "string"
+ },
+ {
+ "name": "price",
+ "type": "u64"
+ },
+ {
+ "name": "symbol",
+ "docs": [
+ "The symbol for the asset"
+ ],
+ "type": "string"
+ },
+ {
+ "name": "sellerFeeBasisPoints",
+ "docs": [
+ "Royalty basis points that goes to creators in secondary sales (0-10000)"
+ ],
+ "type": "u16"
+ },
+ {
+ "name": "maxSupply",
+ "type": "u64"
+ },
+ {
+ "name": "isMutable",
+ "type": "bool"
+ },
+ {
+ "name": "retainAuthority",
+ "type": "bool"
+ },
+ {
+ "name": "goLiveDate",
+ "type": {
+ "option": "i64"
+ }
+ },
+ {
+ "name": "endSettings",
+ "type": {
+ "option": {
+ "defined": "EndSettings"
+ }
+ }
+ },
+ {
+ "name": "creators",
+ "type": {
+ "vec": {
+ "defined": "Creator"
+ }
+ }
+ },
+ {
+ "name": "hiddenSettings",
+ "type": {
+ "option": {
+ "defined": "HiddenSettings"
+ }
+ }
+ },
+ {
+ "name": "whitelistMintSettings",
+ "type": {
+ "option": {
+ "defined": "WhitelistMintSettings"
+ }
+ }
+ },
+ {
+ "name": "itemsAvailable",
+ "type": "u64"
+ },
+ {
+ "name": "gatekeeper",
+ "docs": [
+ "If [`Some`] requires gateway tokens on mint"
+ ],
+ "type": {
+ "option": {
+ "defined": "GatekeeperConfig"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "ConfigLine",
+ "docs": [
+ "Individual config line for storing NFT data pre-mint."
+ ],
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "name": "uri",
+ "docs": [
+ "URI pointing to JSON representing the asset"
+ ],
+ "type": "string"
+ }
+ ]
+ }
+ },
+ {
+ "name": "EndSettings",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "endSettingType",
+ "type": {
+ "defined": "EndSettingType"
+ }
+ },
+ {
+ "name": "number",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Creator",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "address",
+ "type": "publicKey"
+ },
+ {
+ "name": "verified",
+ "type": "bool"
+ },
+ {
+ "name": "share",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "HiddenSettings",
+ "docs": [
+ "Hidden Settings for large mints used with offline data."
+ ],
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "name": "uri",
+ "type": "string"
+ },
+ {
+ "name": "hash",
+ "type": {
+ "array": [
+ "u8",
+ 32
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "WhitelistMintSettings",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "mode",
+ "type": {
+ "defined": "WhitelistMintMode"
+ }
+ },
+ {
+ "name": "mint",
+ "type": "publicKey"
+ },
+ {
+ "name": "presale",
+ "type": "bool"
+ },
+ {
+ "name": "discountPrice",
+ "type": {
+ "option": "u64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "GatekeeperConfig",
+ "docs": [
+ "Configurations options for the gatekeeper."
+ ],
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "gatekeeperNetwork",
+ "docs": [
+ "The network for the gateway token required"
+ ],
+ "type": "publicKey"
+ },
+ {
+ "name": "expireOnUse",
+ "docs": [
+ "Whether or not the token should expire after minting.",
+ "The gatekeeper network must support this if true."
+ ],
+ "type": "bool"
+ }
+ ]
+ }
+ },
+ {
+ "name": "EndSettingType",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Date"
+ },
+ {
+ "name": "Amount"
+ }
+ ]
+ }
+ },
+ {
+ "name": "WhitelistMintMode",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "BurnEveryTime"
+ },
+ {
+ "name": "NeverBurn"
+ }
+ ]
+ }
+ }
+ ],
+ "errors": [
+ {
+ "code": 6000,
+ "name": "IncorrectOwner",
+ "msg": "Account does not have correct owner!"
+ },
+ {
+ "code": 6001,
+ "name": "Uninitialized",
+ "msg": "Account is not initialized!"
+ },
+ {
+ "code": 6002,
+ "name": "MintMismatch",
+ "msg": "Mint Mismatch!"
+ },
+ {
+ "code": 6003,
+ "name": "IndexGreaterThanLength",
+ "msg": "Index greater than length!"
+ },
+ {
+ "code": 6004,
+ "name": "NumericalOverflowError",
+ "msg": "Numerical overflow error!"
+ },
+ {
+ "code": 6005,
+ "name": "TooManyCreators",
+ "msg": "Can only provide up to 4 creators to candy machine (because candy machine is one)!"
+ },
+ {
+ "code": 6006,
+ "name": "UuidMustBeExactly6Length",
+ "msg": "Uuid must be exactly of 6 length"
+ },
+ {
+ "code": 6007,
+ "name": "NotEnoughTokens",
+ "msg": "Not enough tokens to pay for this minting"
+ },
+ {
+ "code": 6008,
+ "name": "NotEnoughSOL",
+ "msg": "Not enough SOL to pay for this minting"
+ },
+ {
+ "code": 6009,
+ "name": "TokenTransferFailed",
+ "msg": "Token transfer failed"
+ },
+ {
+ "code": 6010,
+ "name": "CandyMachineEmpty",
+ "msg": "Candy machine is empty!"
+ },
+ {
+ "code": 6011,
+ "name": "CandyMachineNotLive",
+ "msg": "Candy machine is not live!"
+ },
+ {
+ "code": 6012,
+ "name": "HiddenSettingsConfigsDoNotHaveConfigLines",
+ "msg": "Configs that are using hidden uris do not have config lines, they have a single hash representing hashed order"
+ },
+ {
+ "code": 6013,
+ "name": "CannotChangeNumberOfLines",
+ "msg": "Cannot change number of lines unless is a hidden config"
+ },
+ {
+ "code": 6014,
+ "name": "DerivedKeyInvalid",
+ "msg": "Derived key invalid"
+ },
+ {
+ "code": 6015,
+ "name": "PublicKeyMismatch",
+ "msg": "Public key mismatch"
+ },
+ {
+ "code": 6016,
+ "name": "NoWhitelistToken",
+ "msg": "No whitelist token present"
+ },
+ {
+ "code": 6017,
+ "name": "TokenBurnFailed",
+ "msg": "Token burn failed"
+ },
+ {
+ "code": 6018,
+ "name": "GatewayAppMissing",
+ "msg": "Missing gateway app when required"
+ },
+ {
+ "code": 6019,
+ "name": "GatewayTokenMissing",
+ "msg": "Missing gateway token when required"
+ },
+ {
+ "code": 6020,
+ "name": "GatewayTokenExpireTimeInvalid",
+ "msg": "Invalid gateway token expire time"
+ },
+ {
+ "code": 6021,
+ "name": "NetworkExpireFeatureMissing",
+ "msg": "Missing gateway network expire feature when required"
+ },
+ {
+ "code": 6022,
+ "name": "CannotFindUsableConfigLine",
+ "msg": "Unable to find an unused config line near your random number index"
+ },
+ {
+ "code": 6023,
+ "name": "InvalidString",
+ "msg": "Invalid string"
+ },
+ {
+ "code": 6024,
+ "name": "SuspiciousTransaction",
+ "msg": "Suspicious transaction detected"
+ },
+ {
+ "code": 6025,
+ "name": "CannotSwitchToHiddenSettings",
+ "msg": "Cannot Switch to Hidden Settings after items available is greater than 0"
+ },
+ {
+ "code": 6026,
+ "name": "IncorrectSlotHashesPubkey",
+ "msg": "Incorrect SlotHashes PubKey"
+ },
+ {
+ "code": 6027,
+ "name": "IncorrectCollectionAuthority",
+ "msg": "Incorrect collection NFT authority"
+ },
+ {
+ "code": 6028,
+ "name": "MismatchedCollectionPDA",
+ "msg": "Collection PDA address is invalid"
+ },
+ {
+ "code": 6029,
+ "name": "MismatchedCollectionMint",
+ "msg": "Provided mint account doesn't match collection PDA mint"
+ },
+ {
+ "code": 6030,
+ "name": "SlotHashesEmpty",
+ "msg": "Slot hashes Sysvar is empty"
+ },
+ {
+ "code": 6031,
+ "name": "MetadataAccountMustBeEmpty",
+ "msg": "The metadata account has data in it, and this must be empty to mint a new NFT"
+ },
+ {
+ "code": 6032,
+ "name": "MissingSetCollectionDuringMint",
+ "msg": "Missing set collection during mint IX for Candy Machine with collection set"
+ },
+ {
+ "code": 6033,
+ "name": "NoChangingCollectionDuringMint",
+ "msg": "Can't change collection settings after items have begun to be minted"
+ },
+ {
+ "code": 6034,
+ "name": "CandyCollectionRequiresRetainAuthority",
+ "msg": "Retain authority must be true for Candy Machines with a collection set"
+ },
+ {
+ "code": 6035,
+ "name": "GatewayProgramError",
+ "msg": "Error within Gateway program"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/cashiers_check.json b/basics/anchorpy-main/tests/idls/cashiers_check.json
new file mode 100644
index 0000000..0b24577
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/cashiers_check.json
@@ -0,0 +1,191 @@
+{
+ "version": "0.0.0",
+ "name": "cashiers_check",
+ "instructions": [
+ {
+ "name": "createCheck",
+ "accounts": [
+ {
+ "name": "check",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "checkSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "from",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "to",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "memo",
+ "type": {
+ "option": "string"
+ }
+ },
+ {
+ "name": "nonce",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "cashCheck",
+ "accounts": [
+ {
+ "name": "check",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "checkSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "to",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "cancelCheck",
+ "accounts": [
+ {
+ "name": "check",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "checkSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "from",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Check",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "from",
+ "type": "publicKey"
+ },
+ {
+ "name": "to",
+ "type": "publicKey"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "memo",
+ "type": {
+ "option": "string"
+ }
+ },
+ {
+ "name": "vault",
+ "type": "publicKey"
+ },
+ {
+ "name": "nonce",
+ "type": "u8"
+ },
+ {
+ "name": "burned",
+ "type": "bool"
+ }
+ ]
+ }
+ }
+ ],
+ "errors": [
+ {
+ "code": 300,
+ "name": "InvalidCheckNonce",
+ "msg": "The given nonce does not create a valid program derived address."
+ },
+ {
+ "code": 301,
+ "name": "InvalidCheckSigner",
+ "msg": "The derived check signer does not match that which was given."
+ },
+ {
+ "code": 302,
+ "name": "AlreadyBurned",
+ "msg": "The given check has already been burned."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/chat.json b/basics/anchorpy-main/tests/idls/chat.json
new file mode 100644
index 0000000..c911efa
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/chat.json
@@ -0,0 +1,157 @@
+{
+ "version": "0.0.0",
+ "name": "chat",
+ "instructions": [
+ {
+ "name": "createUser",
+ "accounts": [
+ {
+ "name": "user",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "name",
+ "type": "string"
+ }
+ ]
+ },
+ {
+ "name": "createChatRoom",
+ "accounts": [
+ {
+ "name": "chatRoom",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "name",
+ "type": "string"
+ }
+ ]
+ },
+ {
+ "name": "sendMessage",
+ "accounts": [
+ {
+ "name": "user",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "chatRoom",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "msg",
+ "type": "string"
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "User",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ }
+ ]
+ }
+ },
+ {
+ "name": "ChatRoom",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "head",
+ "type": "u64"
+ },
+ {
+ "name": "tail",
+ "type": "u64"
+ },
+ {
+ "name": "name",
+ "type": {
+ "array": [
+ "u8",
+ 280
+ ]
+ }
+ },
+ {
+ "name": "messages",
+ "type": {
+ "array": [
+ {
+ "defined": "Message"
+ },
+ 33607
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "Message",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "from",
+ "type": "publicKey"
+ },
+ {
+ "name": "data",
+ "type": {
+ "array": [
+ "u8",
+ 280
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "errors": [
+ {
+ "code": 300,
+ "name": "Unknown"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/clientgen_example_program.json b/basics/anchorpy-main/tests/idls/clientgen_example_program.json
new file mode 100644
index 0000000..f5b322d
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/clientgen_example_program.json
@@ -0,0 +1,737 @@
+{
+ "version": "0.1.0",
+ "name": "example_program",
+ "instructions": [
+ {
+ "name": "initialize",
+ "accounts": [
+ {
+ "name": "state",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "nested",
+ "accounts": [
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "initializeWithValues",
+ "accounts": [
+ {
+ "name": "state",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "nested",
+ "accounts": [
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "boolField",
+ "type": "bool"
+ },
+ {
+ "name": "u8Field",
+ "type": "u8"
+ },
+ {
+ "name": "i8Field",
+ "type": "i8"
+ },
+ {
+ "name": "u16Field",
+ "type": "u16"
+ },
+ {
+ "name": "i16Field",
+ "type": "i16"
+ },
+ {
+ "name": "u32Field",
+ "type": "u32"
+ },
+ {
+ "name": "i32Field",
+ "type": "i32"
+ },
+ {
+ "name": "f32Field",
+ "type": "f32"
+ },
+ {
+ "name": "u64Field",
+ "type": "u64"
+ },
+ {
+ "name": "i64Field",
+ "type": "i64"
+ },
+ {
+ "name": "f64Field",
+ "type": "f64"
+ },
+ {
+ "name": "u128Field",
+ "type": "u128"
+ },
+ {
+ "name": "i128Field",
+ "type": "i128"
+ },
+ {
+ "name": "bytesField",
+ "type": "bytes"
+ },
+ {
+ "name": "stringField",
+ "type": "string"
+ },
+ {
+ "name": "pubkeyField",
+ "type": "publicKey"
+ },
+ {
+ "name": "vecField",
+ "type": {
+ "vec": "u64"
+ }
+ },
+ {
+ "name": "vecStructField",
+ "type": {
+ "vec": {
+ "defined": "FooStruct"
+ }
+ }
+ },
+ {
+ "name": "optionField",
+ "type": {
+ "option": "bool"
+ }
+ },
+ {
+ "name": "optionStructField",
+ "type": {
+ "option": {
+ "defined": "FooStruct"
+ }
+ }
+ },
+ {
+ "name": "structField",
+ "type": {
+ "defined": "FooStruct"
+ }
+ },
+ {
+ "name": "arrayField",
+ "type": {
+ "array": [
+ "bool",
+ 3
+ ]
+ }
+ },
+ {
+ "name": "enumField1",
+ "type": {
+ "defined": "FooEnum"
+ }
+ },
+ {
+ "name": "enumField2",
+ "type": {
+ "defined": "FooEnum"
+ }
+ },
+ {
+ "name": "enumField3",
+ "type": {
+ "defined": "FooEnum"
+ }
+ },
+ {
+ "name": "enumField4",
+ "type": {
+ "defined": "FooEnum"
+ }
+ }
+ ]
+ },
+ {
+ "name": "initializeWithValues2",
+ "accounts": [
+ {
+ "name": "state",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "vecOfOption",
+ "type": {
+ "vec": {
+ "option": "u64"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "causeError",
+ "accounts": [],
+ "args": []
+ },
+ {
+ "name": "initMyAccount",
+ "accounts": [
+ {
+ "name": "base",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "base2",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "account",
+ "isMut": false,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "another-seed"
+ },
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "test"
+ },
+ {
+ "kind": "const",
+ "type": {
+ "array": [
+ "u8",
+ 2
+ ]
+ },
+ "value": [
+ 104,
+ 105
+ ]
+ },
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "hi"
+ },
+ {
+ "kind": "const",
+ "type": "u8",
+ "value": 1
+ },
+ {
+ "kind": "const",
+ "type": "u32",
+ "value": 2
+ },
+ {
+ "kind": "const",
+ "type": "u64",
+ "value": 3
+ }
+ ]
+ }
+ },
+ {
+ "name": "nested",
+ "accounts": [
+ {
+ "name": "accountNested",
+ "isMut": false,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "nested-seed"
+ },
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "test"
+ },
+ {
+ "kind": "const",
+ "type": {
+ "array": [
+ "u8",
+ 2
+ ]
+ },
+ "value": [
+ 104,
+ 105
+ ]
+ },
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "hi"
+ },
+ {
+ "kind": "const",
+ "type": "u8",
+ "value": 1
+ },
+ {
+ "kind": "const",
+ "type": "u32",
+ "value": 2
+ },
+ {
+ "kind": "const",
+ "type": "u64",
+ "value": 3
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "seedA",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "incrementStateWhenPresent",
+ "accounts": [
+ {
+ "name": "firstState",
+ "isMut": true,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "secondState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "MyAccount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "BaseAccount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "baseData",
+ "type": "u64"
+ },
+ {
+ "name": "baseDataKey",
+ "type": "publicKey"
+ }
+ ]
+ }
+ },
+ {
+ "name": "State",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "boolField",
+ "type": "bool"
+ },
+ {
+ "name": "u8Field",
+ "type": "u8"
+ },
+ {
+ "name": "i8Field",
+ "type": "i8"
+ },
+ {
+ "name": "u16Field",
+ "type": "u16"
+ },
+ {
+ "name": "i16Field",
+ "type": "i16"
+ },
+ {
+ "name": "u32Field",
+ "type": "u32"
+ },
+ {
+ "name": "i32Field",
+ "type": "i32"
+ },
+ {
+ "name": "f32Field",
+ "type": "f32"
+ },
+ {
+ "name": "u64Field",
+ "type": "u64"
+ },
+ {
+ "name": "i64Field",
+ "type": "i64"
+ },
+ {
+ "name": "f64Field",
+ "type": "f64"
+ },
+ {
+ "name": "u128Field",
+ "type": "u128"
+ },
+ {
+ "name": "i128Field",
+ "type": "i128"
+ },
+ {
+ "name": "bytesField",
+ "type": "bytes"
+ },
+ {
+ "name": "stringField",
+ "type": "string"
+ },
+ {
+ "name": "pubkeyField",
+ "type": "publicKey"
+ },
+ {
+ "name": "vecField",
+ "type": {
+ "vec": "u64"
+ }
+ },
+ {
+ "name": "vecStructField",
+ "type": {
+ "vec": {
+ "defined": "FooStruct"
+ }
+ }
+ },
+ {
+ "name": "optionField",
+ "type": {
+ "option": "bool"
+ }
+ },
+ {
+ "name": "optionStructField",
+ "type": {
+ "option": {
+ "defined": "FooStruct"
+ }
+ }
+ },
+ {
+ "name": "structField",
+ "type": {
+ "defined": "FooStruct"
+ }
+ },
+ {
+ "name": "arrayField",
+ "type": {
+ "array": [
+ "bool",
+ 3
+ ]
+ }
+ },
+ {
+ "name": "enumField1",
+ "type": {
+ "defined": "FooEnum"
+ }
+ },
+ {
+ "name": "enumField2",
+ "type": {
+ "defined": "FooEnum"
+ }
+ },
+ {
+ "name": "enumField3",
+ "type": {
+ "defined": "FooEnum"
+ }
+ },
+ {
+ "name": "enumField4",
+ "type": {
+ "defined": "FooEnum"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "State2",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "vecOfOption",
+ "type": {
+ "vec": {
+ "option": "u64"
+ }
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "BarStruct",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "someField",
+ "type": "bool"
+ },
+ {
+ "name": "otherField",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "FooStruct",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "field1",
+ "type": "u8"
+ },
+ {
+ "name": "field2",
+ "type": "u16"
+ },
+ {
+ "name": "nested",
+ "type": {
+ "defined": "BarStruct"
+ }
+ },
+ {
+ "name": "vecNested",
+ "type": {
+ "vec": {
+ "defined": "BarStruct"
+ }
+ }
+ },
+ {
+ "name": "optionNested",
+ "type": {
+ "option": {
+ "defined": "BarStruct"
+ }
+ }
+ },
+ {
+ "name": "enumField",
+ "type": {
+ "defined": "FooEnum"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "FooEnum",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Unnamed",
+ "fields": [
+ "bool",
+ "u8",
+ {
+ "defined": "BarStruct"
+ }
+ ]
+ },
+ {
+ "name": "UnnamedSingle",
+ "fields": [
+ {
+ "defined": "BarStruct"
+ }
+ ]
+ },
+ {
+ "name": "Named",
+ "fields": [
+ {
+ "name": "bool_field",
+ "type": "bool"
+ },
+ {
+ "name": "u8_field",
+ "type": "u8"
+ },
+ {
+ "name": "nested",
+ "type": {
+ "defined": "BarStruct"
+ }
+ }
+ ]
+ },
+ {
+ "name": "Struct",
+ "fields": [
+ {
+ "defined": "BarStruct"
+ }
+ ]
+ },
+ {
+ "name": "OptionStruct",
+ "fields": [
+ {
+ "option": {
+ "defined": "BarStruct"
+ }
+ }
+ ]
+ },
+ {
+ "name": "VecStruct",
+ "fields": [
+ {
+ "vec": {
+ "defined": "BarStruct"
+ }
+ }
+ ]
+ },
+ {
+ "name": "NoFields"
+ }
+ ]
+ }
+ }
+ ],
+ "errors": [
+ {
+ "code": 6000,
+ "name": "SomeError",
+ "msg": "Example error."
+ },
+ {
+ "code": 6001,
+ "name": "OtherError",
+ "msg": "Another error."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/composite.json b/basics/anchorpy-main/tests/idls/composite.json
new file mode 100644
index 0000000..e8d15b7
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/composite.json
@@ -0,0 +1,86 @@
+{
+ "version": "0.0.0",
+ "name": "composite",
+ "instructions": [
+ {
+ "name": "initialize",
+ "accounts": [
+ {
+ "name": "dummyA",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "dummyB",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "compositeUpdate",
+ "accounts": [
+ {
+ "name": "foo",
+ "accounts": [
+ {
+ "name": "dummyA",
+ "isMut": true,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "bar",
+ "accounts": [
+ {
+ "name": "dummyB",
+ "isMut": true,
+ "isSigner": false
+ }
+ ]
+ }
+ ],
+ "args": [
+ {
+ "name": "dummyA",
+ "type": "u64"
+ },
+ {
+ "name": "dummyB",
+ "type": "u64"
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "DummyA",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "DummyB",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ }
+ ],
+ "metadata": {
+ "address": "FYuVUPk3hmpT44GjCTL6w8Z3kYQoYBAWZMXEi4P63xto"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/counter_auth.json b/basics/anchorpy-main/tests/idls/counter_auth.json
new file mode 100644
index 0000000..4ad926a
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/counter_auth.json
@@ -0,0 +1,5 @@
+{
+ "version": "0.0.0",
+ "name": "counter_auth",
+ "instructions": []
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/errors.json b/basics/anchorpy-main/tests/idls/errors.json
new file mode 100644
index 0000000..346f8a4
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/errors.json
@@ -0,0 +1,88 @@
+{
+ "version": "0.0.0",
+ "name": "errors",
+ "instructions": [
+ {
+ "name": "hello",
+ "accounts": [],
+ "args": []
+ },
+ {
+ "name": "helloNoMsg",
+ "accounts": [],
+ "args": []
+ },
+ {
+ "name": "helloNext",
+ "accounts": [],
+ "args": []
+ },
+ {
+ "name": "mutError",
+ "accounts": [
+ {
+ "name": "myAccount",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "hasOneError",
+ "accounts": [
+ {
+ "name": "myAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "signerError",
+ "accounts": [
+ {
+ "name": "myAccount",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "HasOneAccount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "owner",
+ "type": "publicKey"
+ }
+ ]
+ }
+ }
+ ],
+ "errors": [
+ {
+ "code": 300,
+ "name": "Hello",
+ "msg": "This is an error message clients will automatically display"
+ },
+ {
+ "code": 423,
+ "name": "HelloNoMsg"
+ },
+ {
+ "code": 424,
+ "name": "HelloNext"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/escrow.json b/basics/anchorpy-main/tests/idls/escrow.json
new file mode 100644
index 0000000..5d7c733
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/escrow.json
@@ -0,0 +1,161 @@
+{
+ "version": "0.0.0",
+ "name": "escrow",
+ "instructions": [
+ {
+ "name": "initializeEscrow",
+ "accounts": [
+ {
+ "name": "initializer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "initializerDepositTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "initializerReceiveTokenAccount",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "escrowAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "initializerAmount",
+ "type": "u64"
+ },
+ {
+ "name": "takerAmount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "cancelEscrow",
+ "accounts": [
+ {
+ "name": "initializer",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "pdaDepositTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "pdaAccount",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "escrowAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "exchange",
+ "accounts": [
+ {
+ "name": "taker",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "takerDepositTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "takerReceiveTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "pdaDepositTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "initializerReceiveTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "initializerMainAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "escrowAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "pdaAccount",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "EscrowAccount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "initializerKey",
+ "type": "publicKey"
+ },
+ {
+ "name": "initializerDepositTokenAccount",
+ "type": "publicKey"
+ },
+ {
+ "name": "initializerReceiveTokenAccount",
+ "type": "publicKey"
+ },
+ {
+ "name": "initializerAmount",
+ "type": "u64"
+ },
+ {
+ "name": "takerAmount",
+ "type": "u64"
+ }
+ ]
+ }
+ }
+ ],
+ "metadata": {
+ "address": "38VPDKPpsXerxe7oWCXGQtm5usFGXrf65tbF3A7cs518"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/events.json b/basics/anchorpy-main/tests/idls/events.json
new file mode 100644
index 0000000..3de103d
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/events.json
@@ -0,0 +1,28 @@
+{
+ "version": "0.0.0",
+ "name": "events",
+ "instructions": [
+ {
+ "name": "initialize",
+ "accounts": [],
+ "args": []
+ }
+ ],
+ "events": [
+ {
+ "name": "MyEvent",
+ "fields": [
+ {
+ "name": "data",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "label",
+ "type": "string",
+ "index": true
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/ido_pool.json b/basics/anchorpy-main/tests/idls/ido_pool.json
new file mode 100644
index 0000000..430c4d2
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/ido_pool.json
@@ -0,0 +1,397 @@
+{
+ "version": "0.0.0",
+ "name": "ido_pool",
+ "instructions": [
+ {
+ "name": "initializePool",
+ "accounts": [
+ {
+ "name": "poolAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "poolSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "redeemableMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "usdcMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "poolWatermelon",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "poolUsdc",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "distributionAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "creatorWatermelon",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "numIdoTokens",
+ "type": "u64"
+ },
+ {
+ "name": "nonce",
+ "type": "u8"
+ },
+ {
+ "name": "startIdoTs",
+ "type": "i64"
+ },
+ {
+ "name": "endDepositsTs",
+ "type": "i64"
+ },
+ {
+ "name": "endIdoTs",
+ "type": "i64"
+ }
+ ]
+ },
+ {
+ "name": "exchangeUsdcForRedeemable",
+ "accounts": [
+ {
+ "name": "poolAccount",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "poolSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "redeemableMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "poolUsdc",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "userAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "userUsdc",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "userRedeemable",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "exchangeRedeemableForUsdc",
+ "accounts": [
+ {
+ "name": "poolAccount",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "poolSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "redeemableMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "poolUsdc",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "userAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "userUsdc",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "userRedeemable",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "exchangeRedeemableForWatermelon",
+ "accounts": [
+ {
+ "name": "poolAccount",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "poolSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "redeemableMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "poolWatermelon",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "userAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "userWatermelon",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "userRedeemable",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "withdrawPoolUsdc",
+ "accounts": [
+ {
+ "name": "poolAccount",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "poolSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "poolUsdc",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "distributionAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "creatorUsdc",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "PoolAccount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "redeemableMint",
+ "type": "publicKey"
+ },
+ {
+ "name": "poolWatermelon",
+ "type": "publicKey"
+ },
+ {
+ "name": "watermelonMint",
+ "type": "publicKey"
+ },
+ {
+ "name": "poolUsdc",
+ "type": "publicKey"
+ },
+ {
+ "name": "distributionAuthority",
+ "type": "publicKey"
+ },
+ {
+ "name": "nonce",
+ "type": "u8"
+ },
+ {
+ "name": "numIdoTokens",
+ "type": "u64"
+ },
+ {
+ "name": "startIdoTs",
+ "type": "i64"
+ },
+ {
+ "name": "endDepositsTs",
+ "type": "i64"
+ },
+ {
+ "name": "endIdoTs",
+ "type": "i64"
+ }
+ ]
+ }
+ }
+ ],
+ "errors": [
+ {
+ "code": 300,
+ "name": "IdoFuture",
+ "msg": "IDO must start in the future"
+ },
+ {
+ "code": 301,
+ "name": "SeqTimes",
+ "msg": "IDO times are non-sequential"
+ },
+ {
+ "code": 302,
+ "name": "StartIdoTime",
+ "msg": "IDO has not started"
+ },
+ {
+ "code": 303,
+ "name": "EndDepositsTime",
+ "msg": "Deposits period has ended"
+ },
+ {
+ "code": 304,
+ "name": "EndIdoTime",
+ "msg": "IDO has ended"
+ },
+ {
+ "code": 305,
+ "name": "IdoNotOver",
+ "msg": "IDO has not finished yet"
+ },
+ {
+ "code": 306,
+ "name": "LowUsdc",
+ "msg": "Insufficient USDC"
+ },
+ {
+ "code": 307,
+ "name": "LowRedeemable",
+ "msg": "Insufficient redeemable tokens"
+ },
+ {
+ "code": 308,
+ "name": "UsdcNotEqRedeem",
+ "msg": "USDC total and redeemable total don't match"
+ },
+ {
+ "code": 309,
+ "name": "InvalidNonce",
+ "msg": "Given nonce is invalid"
+ }
+ ],
+ "metadata": {
+ "address": "6iQsUPMA3k453npuvqbgARkSudA8YEtuDersUW7J5Ak1"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/jet.json b/basics/anchorpy-main/tests/idls/jet.json
new file mode 100644
index 0000000..9269654
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/jet.json
@@ -0,0 +1,1905 @@
+{
+ "version": "0.0.0",
+ "name": "jet",
+ "instructions": [
+ {
+ "name": "initMarket",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "owner",
+ "type": "publicKey"
+ },
+ {
+ "name": "quoteCurrency",
+ "type": "string"
+ },
+ {
+ "name": "quoteTokenMint",
+ "type": "publicKey"
+ }
+ ]
+ },
+ {
+ "name": "initReserve",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "feeNoteVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "dexSwapTokens",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "dexOpenOrders",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "dexMarket",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "dexProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "oraclePrice",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "oracleProduct",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "depositNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "quoteTokenMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": {
+ "defined": "InitReserveBumpSeeds"
+ }
+ },
+ {
+ "name": "config",
+ "type": {
+ "defined": "ReserveConfig"
+ }
+ }
+ ]
+ },
+ {
+ "name": "updateReserveConfig",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "newConfig",
+ "type": {
+ "defined": "ReserveConfig"
+ }
+ }
+ ]
+ },
+ {
+ "name": "initDepositAccount",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "depositNoteMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "depositor",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "depositAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "initCollateralAccount",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "obligation",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "depositNoteMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "collateralAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "initLoanAccount",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "obligation",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "loanNoteMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "loanAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "initObligation",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "borrower",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "obligation",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "setMarketOwner",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "newOwner",
+ "type": "publicKey"
+ }
+ ]
+ },
+ {
+ "name": "setMarketFlags",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "flags",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "closeDepositAccount",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "depositNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "depositor",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "depositAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "receiverAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "deposit",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "depositNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "depositor",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "depositAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "depositSource",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ }
+ }
+ ]
+ },
+ {
+ "name": "withdraw",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "depositNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "depositor",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "depositAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "withdrawAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ }
+ }
+ ]
+ },
+ {
+ "name": "depositCollateral",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "obligation",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "depositAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "collateralAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": {
+ "defined": "DepositCollateralBumpSeeds"
+ }
+ },
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ }
+ }
+ ]
+ },
+ {
+ "name": "withdrawCollateral",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "obligation",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "depositAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "collateralAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": {
+ "defined": "WithdrawCollateralBumpSeeds"
+ }
+ },
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ }
+ }
+ ]
+ },
+ {
+ "name": "borrow",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "obligation",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "borrower",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "loanAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "receiverAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ }
+ }
+ ]
+ },
+ {
+ "name": "repay",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "obligation",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payerAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ }
+ }
+ ]
+ },
+ {
+ "name": "liquidate",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "obligation",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "collateralReserve",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "collateralAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payerAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "receiverAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ }
+ },
+ {
+ "name": "minCollateral",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "mockLiquidateDex",
+ "accounts": [
+ {
+ "name": "sourceMarket",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "openOrders",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "requestQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "eventQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "bids",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "asks",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "coinVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "pcVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vaultSigner",
+ "isMut": false,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "targetMarket",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "openOrders",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "requestQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "eventQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "bids",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "asks",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "coinVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "pcVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vaultSigner",
+ "isMut": false,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "toLiquidate",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "obligation",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanReserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanReserveVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "loanAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "collateralReserve",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "collateralReserveVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "depositNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "collateralAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "dexSwapTokens",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "dexProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ]
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "refreshReserve",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "marketAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "reserve",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "feeNoteVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "depositNoteMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "pythOraclePrice",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Market",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "version",
+ "type": "u32"
+ },
+ {
+ "name": "quoteExponent",
+ "type": "i32"
+ },
+ {
+ "name": "quoteCurrency",
+ "type": {
+ "array": [
+ "u8",
+ 15
+ ]
+ }
+ },
+ {
+ "name": "authorityBumpSeed",
+ "type": {
+ "array": [
+ "u8",
+ 1
+ ]
+ }
+ },
+ {
+ "name": "authoritySeed",
+ "type": "publicKey"
+ },
+ {
+ "name": "marketAuthority",
+ "type": "publicKey"
+ },
+ {
+ "name": "owner",
+ "type": "publicKey"
+ },
+ {
+ "name": "quoteTokenMint",
+ "type": "publicKey"
+ },
+ {
+ "name": "flags",
+ "type": "u64"
+ },
+ {
+ "name": "reserved",
+ "type": {
+ "array": [
+ "u8",
+ 352
+ ]
+ }
+ },
+ {
+ "name": "reserves",
+ "type": {
+ "array": [
+ "u8",
+ 12288
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Obligation",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "version",
+ "type": "u32"
+ },
+ {
+ "name": "reserved0",
+ "type": "u32"
+ },
+ {
+ "name": "market",
+ "type": "publicKey"
+ },
+ {
+ "name": "owner",
+ "type": "publicKey"
+ },
+ {
+ "name": "reserved1",
+ "type": {
+ "array": [
+ "u8",
+ 184
+ ]
+ }
+ },
+ {
+ "name": "cached",
+ "type": {
+ "array": [
+ "u8",
+ 256
+ ]
+ }
+ },
+ {
+ "name": "collateral",
+ "type": {
+ "array": [
+ "u8",
+ 2048
+ ]
+ }
+ },
+ {
+ "name": "loans",
+ "type": {
+ "array": [
+ "u8",
+ 2048
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Reserve",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "version",
+ "type": "u16"
+ },
+ {
+ "name": "index",
+ "type": "u16"
+ },
+ {
+ "name": "exponent",
+ "type": "i32"
+ },
+ {
+ "name": "market",
+ "type": "publicKey"
+ },
+ {
+ "name": "pythOraclePrice",
+ "type": "publicKey"
+ },
+ {
+ "name": "pythOracleProduct",
+ "type": "publicKey"
+ },
+ {
+ "name": "tokenMint",
+ "type": "publicKey"
+ },
+ {
+ "name": "depositNoteMint",
+ "type": "publicKey"
+ },
+ {
+ "name": "loanNoteMint",
+ "type": "publicKey"
+ },
+ {
+ "name": "vault",
+ "type": "publicKey"
+ },
+ {
+ "name": "feeNoteVault",
+ "type": "publicKey"
+ },
+ {
+ "name": "dexSwapTokens",
+ "type": "publicKey"
+ },
+ {
+ "name": "dexOpenOrders",
+ "type": "publicKey"
+ },
+ {
+ "name": "dexMarket",
+ "type": "publicKey"
+ },
+ {
+ "name": "reserved0",
+ "type": {
+ "array": [
+ "u8",
+ 408
+ ]
+ }
+ },
+ {
+ "name": "config",
+ "type": {
+ "defined": "ReserveConfig"
+ }
+ },
+ {
+ "name": "reserved1",
+ "type": {
+ "array": [
+ "u8",
+ 704
+ ]
+ }
+ },
+ {
+ "name": "state",
+ "type": {
+ "array": [
+ "u8",
+ 512
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "Amount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "units",
+ "type": {
+ "defined": "AmountUnits"
+ }
+ },
+ {
+ "name": "value",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "DepositCollateralBumpSeeds",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "collateralAccount",
+ "type": "u8"
+ },
+ {
+ "name": "depositAccount",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "InitReserveBumpSeeds",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "vault",
+ "type": "u8"
+ },
+ {
+ "name": "feeNoteVault",
+ "type": "u8"
+ },
+ {
+ "name": "dexOpenOrders",
+ "type": "u8"
+ },
+ {
+ "name": "dexSwapTokens",
+ "type": "u8"
+ },
+ {
+ "name": "depositNoteMint",
+ "type": "u8"
+ },
+ {
+ "name": "loanNoteMint",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "ReserveConfig",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "utilizationRate1",
+ "type": "u16"
+ },
+ {
+ "name": "utilizationRate2",
+ "type": "u16"
+ },
+ {
+ "name": "borrowRate0",
+ "type": "u16"
+ },
+ {
+ "name": "borrowRate1",
+ "type": "u16"
+ },
+ {
+ "name": "borrowRate2",
+ "type": "u16"
+ },
+ {
+ "name": "borrowRate3",
+ "type": "u16"
+ },
+ {
+ "name": "minCollateralRatio",
+ "type": "u16"
+ },
+ {
+ "name": "liquidationPremium",
+ "type": "u16"
+ },
+ {
+ "name": "manageFeeCollectionThreshold",
+ "type": "u64"
+ },
+ {
+ "name": "manageFeeRate",
+ "type": "u16"
+ },
+ {
+ "name": "loanOriginationFee",
+ "type": "u16"
+ },
+ {
+ "name": "liquidationSlippage",
+ "type": "u16"
+ },
+ {
+ "name": "reserved0",
+ "type": "u16"
+ },
+ {
+ "name": "liquidationDexTradeMax",
+ "type": "u64"
+ },
+ {
+ "name": "reserved1",
+ "type": {
+ "array": [
+ "u8",
+ 24
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "WithdrawCollateralBumpSeeds",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "collateralAccount",
+ "type": "u8"
+ },
+ {
+ "name": "depositAccount",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "CacheInvalidError",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Expired",
+ "fields": [
+ {
+ "name": "msg",
+ "type": "string"
+ }
+ ]
+ },
+ {
+ "name": "TooNew",
+ "fields": [
+ {
+ "name": "msg",
+ "type": "string"
+ }
+ ]
+ },
+ {
+ "name": "Invalidated"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AmountUnits",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Tokens"
+ },
+ {
+ "name": "DepositNotes"
+ },
+ {
+ "name": "LoanNotes"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Rounding",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Up"
+ },
+ {
+ "name": "Down"
+ }
+ ]
+ }
+ },
+ {
+ "name": "DexSide",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Bid"
+ },
+ {
+ "name": "Ask"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Side",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Collateral"
+ },
+ {
+ "name": "Loan"
+ }
+ ]
+ }
+ },
+ {
+ "name": "JobCompletion",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Partial"
+ },
+ {
+ "name": "Full"
+ }
+ ]
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "BorrowEvent",
+ "fields": [
+ {
+ "name": "borrower",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "reserve",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "debt",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "DepositCollateralEvent",
+ "fields": [
+ {
+ "name": "depositor",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "reserve",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ },
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "LiquidateEvent",
+ "fields": [
+ {
+ "name": "borrower",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "debtReserve",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "collateralReserve",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "paidAmount",
+ "type": {
+ "defined": "Amount"
+ },
+ "index": false
+ },
+ {
+ "name": "collateralAmount",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "RepayEvent",
+ "fields": [
+ {
+ "name": "borrower",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "reserve",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ },
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "WithdrawCollateralEvent",
+ "fields": [
+ {
+ "name": "depositor",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "reserve",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": {
+ "defined": "Amount"
+ },
+ "index": false
+ }
+ ]
+ }
+ ],
+ "errors": [
+ {
+ "code": 300,
+ "name": "ArithmeticError",
+ "msg": "failed to perform some math operation safely"
+ },
+ {
+ "code": 301,
+ "name": "InvalidOracle",
+ "msg": "oracle account provided is not valid"
+ },
+ {
+ "code": 302,
+ "name": "NoFreeReserves",
+ "msg": "no free space left to add a new reserve in the market"
+ },
+ {
+ "code": 303,
+ "name": "NoFreeObligation",
+ "msg": "no free space left to add the new loan or collateral in an obligation"
+ },
+ {
+ "code": 304,
+ "name": "UnregisteredPosition",
+ "msg": "the obligation account doesn't have any record of the loan or collateral account"
+ },
+ {
+ "code": 305,
+ "name": "InvalidOraclePrice",
+ "msg": "the oracle price account has an invalid price value"
+ },
+ {
+ "code": 306,
+ "name": "InsufficientCollateral",
+ "msg": "there is not enough collateral deposited to borrow against"
+ },
+ {
+ "code": 307,
+ "name": "SimultaneousDepositAndBorrow",
+ "msg": "cannot both deposit collateral to and borrow from the same reserve"
+ },
+ {
+ "code": 308,
+ "name": "ObligationHealthy",
+ "msg": "cannot liquidate a healthy position"
+ },
+ {
+ "code": 309,
+ "name": "ObligationUnhealthy",
+ "msg": "cannot perform an action that would leave the obligation unhealthy"
+ },
+ {
+ "code": 310,
+ "name": "ExceptionalReserveState",
+ "msg": "reserve requires special action; call refresh_reserve until up to date"
+ },
+ {
+ "code": 311,
+ "name": "InvalidAmountUnits",
+ "msg": "the units provided in the amount are not valid for the instruction"
+ },
+ {
+ "code": 312,
+ "name": "InvalidDexMarketMints",
+ "msg": "the tokens in the DEX market don't match the reserve and lending market quote token"
+ },
+ {
+ "code": 313,
+ "name": "InvalidMarketAuthority",
+ "msg": "the market authority provided doesn't match the market account"
+ },
+ {
+ "code": 314,
+ "name": "InvalidLiquidationQuoteTokenAccount",
+ "msg": "the quote token account provided cannot be used for liquidations"
+ },
+ {
+ "code": 315,
+ "name": "ObligationAccountMismatch",
+ "msg": "the obligation account doesn't have the collateral/loan registered"
+ },
+ {
+ "code": 316,
+ "name": "UnknownInstruction",
+ "msg": "unknown instruction"
+ },
+ {
+ "code": 317,
+ "name": "Disallowed",
+ "msg": "current conditions prevent an action from being performed"
+ },
+ {
+ "code": 318,
+ "name": "LiquidationSwapSlipped",
+ "msg": "the actual slipped amount on the DEX trade exceeded the threshold configured"
+ },
+ {
+ "code": 319,
+ "name": "CollateralValueTooSmall",
+ "msg": "the collateral value is too small for a DEX trade"
+ },
+ {
+ "code": 320,
+ "name": "LiquidationLowCollateral",
+ "msg": "the collateral returned by the liquidation is smaller than requested"
+ },
+ {
+ "code": 321,
+ "name": "NotSupported",
+ "msg": "this action is currently not supported by this version of the program"
+ },
+ {
+ "code": 322,
+ "name": "MarketHalted",
+ "msg": "the market has currently halted this kind of operation"
+ },
+ {
+ "code": 323,
+ "name": "InvalidParameter",
+ "msg": "a given parameter is not valid"
+ }
+ ],
+ "metadata": {
+ "address": "JPv1rCqrhagNNmJVM5J1he7msQ5ybtvE1nNuHpDHMNU"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/jet_auth.json b/basics/anchorpy-main/tests/idls/jet_auth.json
new file mode 100644
index 0000000..337d251
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/jet_auth.json
@@ -0,0 +1,99 @@
+{
+ "version": "1.0.0",
+ "name": "jet_auth",
+ "instructions": [
+ {
+ "name": "createUserAuth",
+ "accounts": [
+ {
+ "name": "user",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "auth",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [],
+ "returns": null
+ },
+ {
+ "name": "authenticate",
+ "accounts": [
+ {
+ "name": "auth",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [],
+ "returns": null
+ }
+ ],
+ "accounts": [
+ {
+ "name": "UserAuthentication",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "owner",
+ "type": "publicKey"
+ },
+ {
+ "name": "complete",
+ "type": "bool"
+ },
+ {
+ "name": "allowed",
+ "type": "bool"
+ }
+ ]
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "AuthAccountCreated",
+ "fields": [
+ {
+ "name": "user",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "Authenticated",
+ "fields": [
+ {
+ "name": "user",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ }
+ ]
+}
diff --git a/basics/anchorpy-main/tests/idls/jet_rewards.json b/basics/anchorpy-main/tests/idls/jet_rewards.json
new file mode 100644
index 0000000..6894a17
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/jet_rewards.json
@@ -0,0 +1,1177 @@
+{
+ "version": "1.0.0",
+ "name": "jet_rewards",
+ "constants": [
+ {
+ "name": "AWARD",
+ "type": {
+ "defined": "&[u8]"
+ },
+ "value": "b\"award\""
+ },
+ {
+ "name": "DISTRIBUTION",
+ "type": {
+ "defined": "&[u8]"
+ },
+ "value": "b\"distribution\""
+ },
+ {
+ "name": "VAULT",
+ "type": {
+ "defined": "&[u8]"
+ },
+ "value": "b\"vault\""
+ }
+ ],
+ "instructions": [
+ {
+ "name": "airdropCreate",
+ "accounts": [
+ {
+ "name": "airdrop",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rewardVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "tokenMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AirdropCreateParams"
+ }
+ }
+ ],
+ "returns": null
+ },
+ {
+ "name": "airdropAddRecipients",
+ "accounts": [
+ {
+ "name": "airdrop",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AirdropAddRecipientsParams"
+ }
+ }
+ ],
+ "returns": null
+ },
+ {
+ "name": "airdropFinalize",
+ "accounts": [
+ {
+ "name": "airdrop",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rewardVault",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [],
+ "returns": null
+ },
+ {
+ "name": "airdropClose",
+ "accounts": [
+ {
+ "name": "airdrop",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rewardVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "receiver",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenReceiver",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [],
+ "returns": null
+ },
+ {
+ "name": "airdropClaim",
+ "accounts": [
+ {
+ "name": "airdrop",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rewardVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "recipient",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "receiver",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "stakePool",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "stakePoolVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "stakeAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "voterWeightRecord",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "maxVoterWeightRecord",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "stakingProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [],
+ "returns": null
+ },
+ {
+ "name": "distributionCreate",
+ "accounts": [
+ {
+ "name": "distribution",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payerRent",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "payerTokenAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "payerTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "DistributionCreateParams"
+ }
+ }
+ ],
+ "returns": null
+ },
+ {
+ "name": "distributionRelease",
+ "accounts": [
+ {
+ "name": "distribution",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "targetAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [],
+ "returns": null
+ },
+ {
+ "name": "distributionClose",
+ "accounts": [
+ {
+ "name": "distribution",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "receiver",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [],
+ "returns": null
+ },
+ {
+ "name": "awardCreate",
+ "accounts": [
+ {
+ "name": "award",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenSource",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenSourceAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "payerRent",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AwardCreateParams"
+ }
+ }
+ ],
+ "returns": null
+ },
+ {
+ "name": "awardRelease",
+ "accounts": [
+ {
+ "name": "award",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "stakeAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "voterWeightRecord",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "maxVoterWeightRecord",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "stakePool",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "stakePoolVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "stakingProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [],
+ "returns": null
+ },
+ {
+ "name": "awardClose",
+ "accounts": [
+ {
+ "name": "award",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "receiver",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [],
+ "returns": null
+ },
+ {
+ "name": "awardRevoke",
+ "accounts": [
+ {
+ "name": "award",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "receiver",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenReceiver",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [],
+ "returns": null
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Airdrop",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "address",
+ "type": "publicKey"
+ },
+ {
+ "name": "rewardVault",
+ "type": "publicKey"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "expireAt",
+ "type": "i64"
+ },
+ {
+ "name": "stakePool",
+ "type": "publicKey"
+ },
+ {
+ "name": "flags",
+ "type": "u64"
+ },
+ {
+ "name": "shortDesc",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "longDesc",
+ "type": {
+ "array": ["u8", 255]
+ }
+ },
+ {
+ "name": "vaultBump",
+ "type": {
+ "array": ["u8", 1]
+ }
+ },
+ {
+ "name": "targetInfo",
+ "type": {
+ "array": ["u8", 400024]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Award",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "seed",
+ "type": {
+ "array": ["u8", 30]
+ }
+ },
+ {
+ "name": "seedLen",
+ "type": "u8"
+ },
+ {
+ "name": "bumpSeed",
+ "type": {
+ "array": ["u8", 1]
+ }
+ },
+ {
+ "name": "stakeAccount",
+ "type": "publicKey"
+ },
+ {
+ "name": "vault",
+ "type": "publicKey"
+ },
+ {
+ "name": "tokenDistribution",
+ "type": {
+ "defined": "TokenDistribution"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Distribution",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "address",
+ "type": "publicKey"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "vault",
+ "type": "publicKey"
+ },
+ {
+ "name": "seed",
+ "type": {
+ "array": ["u8", 30]
+ }
+ },
+ {
+ "name": "seedLen",
+ "type": "u8"
+ },
+ {
+ "name": "bumpSeed",
+ "type": {
+ "array": ["u8", 1]
+ }
+ },
+ {
+ "name": "targetAccount",
+ "type": "publicKey"
+ },
+ {
+ "name": "tokenDistribution",
+ "type": {
+ "defined": "TokenDistribution"
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "AirdropAddRecipientsParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "startIndex",
+ "type": "u64"
+ },
+ {
+ "name": "recipients",
+ "type": {
+ "vec": {
+ "defined": "AirdropRecipientParam"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "AirdropRecipientParam",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "recipient",
+ "type": "publicKey"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AirdropCreateParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "expireAt",
+ "type": "i64"
+ },
+ {
+ "name": "stakePool",
+ "type": "publicKey"
+ },
+ {
+ "name": "shortDesc",
+ "type": "string"
+ },
+ {
+ "name": "longDesc",
+ "type": "string"
+ },
+ {
+ "name": "flags",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AwardCreateParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "seed",
+ "type": "string"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "stakeAccount",
+ "type": "publicKey"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "beginAt",
+ "type": "u64"
+ },
+ {
+ "name": "endAt",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "DistributionCreateParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "seed",
+ "type": "string"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "targetAccount",
+ "type": "publicKey"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "beginAt",
+ "type": "u64"
+ },
+ {
+ "name": "endAt",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "TokenDistribution",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "targetAmount",
+ "type": "u64"
+ },
+ {
+ "name": "distributed",
+ "type": "u64"
+ },
+ {
+ "name": "beginAt",
+ "type": "u64"
+ },
+ {
+ "name": "endAt",
+ "type": "u64"
+ },
+ {
+ "name": "kind",
+ "type": {
+ "defined": "DistributionKind"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "DistributionKind",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Linear"
+ }
+ ]
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "AirdropCreated",
+ "fields": [
+ {
+ "name": "airdrop",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "authority",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "tokenMint",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "params",
+ "type": {
+ "defined": "AirdropCreateParams"
+ },
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AirdropRecipientsAdded",
+ "fields": [
+ {
+ "name": "airdrop",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "rewardAdditional",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "rewardTotal",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "recipientsAdditional",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "recipientsTotal",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "recipients",
+ "type": {
+ "vec": {
+ "defined": "AirdropRecipientParam"
+ }
+ },
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AirdropFinalized",
+ "fields": [
+ {
+ "name": "airdrop",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "rewardTotal",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "recipientsTotal",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "vaultBalance",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AirdropClaimed",
+ "fields": [
+ {
+ "name": "airdrop",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "recipient",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "claimedAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "remainingAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "vaultBalance",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AirdropClosed",
+ "fields": [
+ {
+ "name": "airdrop",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "vaultAmount",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AwardCreated",
+ "fields": [
+ {
+ "name": "award",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "tokenMint",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "params",
+ "type": {
+ "defined": "AwardCreateParams"
+ },
+ "index": false
+ },
+ {
+ "name": "distributionKind",
+ "type": {
+ "defined": "DistributionKind"
+ },
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AwardReleased",
+ "fields": [
+ {
+ "name": "award",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amountReleased",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "totalReleased",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "vaultBalance",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AwardRevoked",
+ "fields": [
+ {
+ "name": "award",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "unreleasedAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "totalReleased",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "vaultAmount",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AwardClosed",
+ "fields": [
+ {
+ "name": "award",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "DistributionCreated",
+ "fields": [
+ {
+ "name": "distribution",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "authority",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "tokenMint",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "params",
+ "type": {
+ "defined": "DistributionCreateParams"
+ },
+ "index": false
+ },
+ {
+ "name": "distributionKind",
+ "type": {
+ "defined": "DistributionKind"
+ },
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "DistributionReleased",
+ "fields": [
+ {
+ "name": "distribution",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amountReleased",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "totalDistributed",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "vaultBalance",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "DistributionClosed",
+ "fields": [
+ {
+ "name": "distribution",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ }
+ ],
+ "errors": [
+ {
+ "code": 13000,
+ "name": "RecipientNotFound"
+ },
+ {
+ "code": 13001,
+ "name": "AddOutOfOrder"
+ },
+ {
+ "code": 13002,
+ "name": "AirdropFinal"
+ },
+ {
+ "code": 13003,
+ "name": "AirdropInsufficientRewardBalance"
+ },
+ {
+ "code": 13004,
+ "name": "AirdropExpired"
+ },
+ {
+ "code": 13005,
+ "name": "AirdropNotFinal"
+ },
+ {
+ "code": 13006,
+ "name": "RecipientsNotSorted"
+ },
+ {
+ "code": 13007,
+ "name": "DistributionNotEnded"
+ },
+ {
+ "code": 13008,
+ "name": "AwardNotFullyVested"
+ }
+ ]
+}
diff --git a/basics/anchorpy-main/tests/idls/merkle_distributor.json b/basics/anchorpy-main/tests/idls/merkle_distributor.json
new file mode 100644
index 0000000..d68ecc8
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/merkle_distributor.json
@@ -0,0 +1,480 @@
+{
+ "version": "0.0.0",
+ "name": "merkle_distributor",
+ "instructions": [
+ {
+ "name": "newDistributor",
+ "accounts": [
+ {
+ "name": "base",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "distributor",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "root",
+ "type": {
+ "array": [
+ "u8",
+ 32
+ ]
+ }
+ },
+ {
+ "name": "temporal",
+ "type": "publicKey"
+ }
+ ]
+ },
+ {
+ "name": "closeDistributor",
+ "accounts": [
+ {
+ "name": "base",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "distributor",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "distributorWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "receiver",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "walletBump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "claim",
+ "accounts": [
+ {
+ "name": "distributor",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "claimStatus",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "from",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "to",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "temporal",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "payer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "index",
+ "type": "u64"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "claimantSecret",
+ "type": "publicKey"
+ },
+ {
+ "name": "proof",
+ "type": {
+ "vec": {
+ "array": [
+ "u8",
+ 32
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "claimCandy",
+ "accounts": [
+ {
+ "name": "distributor",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "distributorWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "claimCount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "temporal",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "payer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "candyMachineConfig",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "candyMachine",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "candyMachineWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "candyMachineMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "candyMachineMetadata",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "candyMachineMasterEdition",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenMetadataProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "candyMachineProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "walletBump",
+ "type": "u8"
+ },
+ {
+ "name": "claimBump",
+ "type": "u8"
+ },
+ {
+ "name": "index",
+ "type": "u64"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "claimantSecret",
+ "type": "publicKey"
+ },
+ {
+ "name": "proof",
+ "type": {
+ "vec": {
+ "array": [
+ "u8",
+ 32
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "MerkleDistributor",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "base",
+ "type": "publicKey"
+ },
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "root",
+ "type": {
+ "array": [
+ "u8",
+ 32
+ ]
+ }
+ },
+ {
+ "name": "temporal",
+ "type": "publicKey"
+ }
+ ]
+ }
+ },
+ {
+ "name": "ClaimStatus",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "isClaimed",
+ "type": "bool"
+ },
+ {
+ "name": "claimant",
+ "type": "publicKey"
+ },
+ {
+ "name": "claimedAt",
+ "type": "i64"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "ClaimCount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "count",
+ "type": "u64"
+ },
+ {
+ "name": "claimant",
+ "type": "publicKey"
+ }
+ ]
+ }
+ },
+ {
+ "name": "CandyMachine",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "wallet",
+ "type": "publicKey"
+ },
+ {
+ "name": "tokenMint",
+ "type": {
+ "option": "publicKey"
+ }
+ },
+ {
+ "name": "config",
+ "type": "publicKey"
+ },
+ {
+ "name": "data",
+ "type": {
+ "defined": "CandyMachineData"
+ }
+ },
+ {
+ "name": "itemsRedeemed",
+ "type": "u64"
+ },
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "CandyMachineData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "uuid",
+ "type": "string"
+ },
+ {
+ "name": "price",
+ "type": "u64"
+ },
+ {
+ "name": "itemsAvailable",
+ "type": "u64"
+ },
+ {
+ "name": "goLiveDate",
+ "type": {
+ "option": "i64"
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "ClaimedEvent",
+ "fields": [
+ {
+ "name": "index",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "claimant",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ }
+ ],
+ "errors": [
+ {
+ "code": 300,
+ "name": "InvalidProof",
+ "msg": "Invalid Merkle proof."
+ },
+ {
+ "code": 301,
+ "name": "DropAlreadyClaimed",
+ "msg": "Drop already claimed."
+ },
+ {
+ "code": 302,
+ "name": "Unauthorized",
+ "msg": "Account is not authorized to execute this instruction"
+ },
+ {
+ "code": 303,
+ "name": "OwnerMismatch",
+ "msg": "Token account owner did not match intended owner"
+ },
+ {
+ "code": 304,
+ "name": "TemporalMismatch",
+ "msg": "Temporal signer did not match distributor"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/multisig.json b/basics/anchorpy-main/tests/idls/multisig.json
new file mode 100644
index 0000000..8b825b9
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/multisig.json
@@ -0,0 +1,277 @@
+{
+ "version": "0.0.0",
+ "name": "multisig",
+ "instructions": [
+ {
+ "name": "createMultisig",
+ "accounts": [
+ {
+ "name": "multisig",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "owners",
+ "type": {
+ "vec": "publicKey"
+ }
+ },
+ {
+ "name": "threshold",
+ "type": "u64"
+ },
+ {
+ "name": "nonce",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "createTransaction",
+ "accounts": [
+ {
+ "name": "multisig",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "transaction",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "proposer",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "pid",
+ "type": "publicKey"
+ },
+ {
+ "name": "accs",
+ "type": {
+ "vec": {
+ "defined": "TransactionAccount"
+ }
+ }
+ },
+ {
+ "name": "data",
+ "type": "bytes"
+ }
+ ]
+ },
+ {
+ "name": "approve",
+ "accounts": [
+ {
+ "name": "multisig",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "transaction",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "setOwners",
+ "accounts": [
+ {
+ "name": "multisig",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "multisigSigner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "owners",
+ "type": {
+ "vec": "publicKey"
+ }
+ }
+ ]
+ },
+ {
+ "name": "changeThreshold",
+ "accounts": [
+ {
+ "name": "multisig",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "multisigSigner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "threshold",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "executeTransaction",
+ "accounts": [
+ {
+ "name": "multisig",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "multisigSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "transaction",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Multisig",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "owners",
+ "type": {
+ "vec": "publicKey"
+ }
+ },
+ {
+ "name": "threshold",
+ "type": "u64"
+ },
+ {
+ "name": "nonce",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Transaction",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "multisig",
+ "type": "publicKey"
+ },
+ {
+ "name": "programId",
+ "type": "publicKey"
+ },
+ {
+ "name": "accounts",
+ "type": {
+ "vec": {
+ "defined": "TransactionAccount"
+ }
+ }
+ },
+ {
+ "name": "data",
+ "type": "bytes"
+ },
+ {
+ "name": "signers",
+ "type": {
+ "vec": "bool"
+ }
+ },
+ {
+ "name": "didExecute",
+ "type": "bool"
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "TransactionAccount",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "pubkey",
+ "type": "publicKey"
+ },
+ {
+ "name": "isSigner",
+ "type": "bool"
+ },
+ {
+ "name": "isWritable",
+ "type": "bool"
+ }
+ ]
+ }
+ }
+ ],
+ "errors": [
+ {
+ "code": 300,
+ "name": "InvalidOwner",
+ "msg": "The given owner is not part of this multisig."
+ },
+ {
+ "code": 301,
+ "name": "NotEnoughSigners",
+ "msg": "Not enough owners signed this transaction."
+ },
+ {
+ "code": 302,
+ "name": "TransactionAlreadySigned",
+ "msg": "Cannot delete a transaction that has been signed by an owner."
+ },
+ {
+ "code": 303,
+ "name": "Overflow",
+ "msg": "Overflow when adding."
+ },
+ {
+ "code": 304,
+ "name": "UnableToDelete",
+ "msg": "Cannot delete a transaction the owner did not create."
+ },
+ {
+ "code": 305,
+ "name": "AlreadyExecuted",
+ "msg": "The given transaction has already been executed."
+ },
+ {
+ "code": 306,
+ "name": "InvalidThreshold",
+ "msg": "Threshold must be less than or equal to the number of owners."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/puppet.json b/basics/anchorpy-main/tests/idls/puppet.json
new file mode 100644
index 0000000..625b61e
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/puppet.json
@@ -0,0 +1,55 @@
+{
+ "version": "0.0.0",
+ "name": "puppet",
+ "instructions": [
+ {
+ "name": "initialize",
+ "accounts": [
+ {
+ "name": "puppet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "setData",
+ "accounts": [
+ {
+ "name": "puppet",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Puppet",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ }
+ ],
+ "metadata": {
+ "address": "61Q5bAAha3NF2gowifnZxaRttM1eyCs4Y3j9YjgMWrqb"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/puppet_master.json b/basics/anchorpy-main/tests/idls/puppet_master.json
new file mode 100644
index 0000000..186d86e
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/puppet_master.json
@@ -0,0 +1,30 @@
+{
+ "version": "0.0.0",
+ "name": "puppet_master",
+ "instructions": [
+ {
+ "name": "pullStrings",
+ "accounts": [
+ {
+ "name": "puppet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "puppetProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "data",
+ "type": "u64"
+ }
+ ]
+ }
+ ],
+ "metadata": {
+ "address": "3UDzsDD9WWPAgHASFHyFdqZz1hFmWpWVCZzLPZabDJxe"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/pyth.json b/basics/anchorpy-main/tests/idls/pyth.json
new file mode 100644
index 0000000..0516aaf
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/pyth.json
@@ -0,0 +1,99 @@
+{
+ "version": "0.0.0",
+ "name": "pyth",
+ "instructions": [
+ {
+ "name": "initialize",
+ "accounts": [
+ {
+ "name": "price",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "price",
+ "type": "i64"
+ },
+ {
+ "name": "expo",
+ "type": "i32"
+ },
+ {
+ "name": "conf",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "setPrice",
+ "accounts": [
+ {
+ "name": "price",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "price",
+ "type": "i64"
+ }
+ ]
+ }
+ ],
+ "types": [
+ {
+ "name": "PriceStatus",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Unknown"
+ },
+ {
+ "name": "Trading"
+ },
+ {
+ "name": "Halted"
+ },
+ {
+ "name": "Auction"
+ }
+ ]
+ }
+ },
+ {
+ "name": "CorpAction",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "NoCorpAct"
+ }
+ ]
+ }
+ },
+ {
+ "name": "PriceType",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Unknown"
+ },
+ {
+ "name": "Price"
+ },
+ {
+ "name": "TWAP"
+ },
+ {
+ "name": "Volatility"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/quarry_mine.json b/basics/anchorpy-main/tests/idls/quarry_mine.json
new file mode 100644
index 0000000..0d5b494
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/quarry_mine.json
@@ -0,0 +1,980 @@
+{
+ "version": "0.0.0",
+ "name": "quarry_mine",
+ "instructions": [
+ {
+ "name": "newRewarder",
+ "accounts": [
+ {
+ "name": "base",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "unusedClock",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "mintWrapper",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rewardsTokenMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "claimFeeTokenAccount",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "setPauseAuthority",
+ "accounts": [
+ {
+ "name": "auth",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": true,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "pauseAuthority",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "pause",
+ "accounts": [
+ {
+ "name": "pauseAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "unpause",
+ "accounts": [
+ {
+ "name": "pauseAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "transferAuthority",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "newAuthority",
+ "type": "publicKey"
+ }
+ ]
+ },
+ {
+ "name": "acceptAuthority",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "setAnnualRewards",
+ "accounts": [
+ {
+ "name": "auth",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": true,
+ "isSigner": false
+ }
+ ]
+ }
+ ],
+ "args": [
+ {
+ "name": "newRate",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "createQuarry",
+ "accounts": [
+ {
+ "name": "quarry",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "auth",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": true,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "tokenMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "unusedClock",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "setRewardsShare",
+ "accounts": [
+ {
+ "name": "auth",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": true,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "quarry",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "newShare",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "setFamine",
+ "accounts": [
+ {
+ "name": "auth",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "rewarder",
+ "isMut": false,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "quarry",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "famineTs",
+ "type": "i64"
+ }
+ ]
+ },
+ {
+ "name": "updateQuarryRewards",
+ "accounts": [
+ {
+ "name": "quarry",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rewarder",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "createMiner",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "miner",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "quarry",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rewarder",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "tokenMint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "minerVault",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "claimRewards",
+ "accounts": [
+ {
+ "name": "mintWrapper",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mintWrapperProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "minter",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rewardsTokenMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rewardsTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "claimFeeTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "stake",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "miner",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "quarry",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "unusedMinerVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "unusedTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rewarder",
+ "isMut": false,
+ "isSigner": false
+ }
+ ]
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "stakeTokens",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "miner",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "quarry",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "minerVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rewarder",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "withdrawTokens",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "miner",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "quarry",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "minerVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rewarder",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "extractFees",
+ "accounts": [
+ {
+ "name": "rewarder",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "claimFeeTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "feeToTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Rewarder",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "base",
+ "type": "publicKey"
+ },
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "pendingAuthority",
+ "type": "publicKey"
+ },
+ {
+ "name": "numQuarries",
+ "type": "u16"
+ },
+ {
+ "name": "annualRewardsRate",
+ "type": "u64"
+ },
+ {
+ "name": "totalRewardsShares",
+ "type": "u64"
+ },
+ {
+ "name": "mintWrapper",
+ "type": "publicKey"
+ },
+ {
+ "name": "rewardsTokenMint",
+ "type": "publicKey"
+ },
+ {
+ "name": "claimFeeTokenAccount",
+ "type": "publicKey"
+ },
+ {
+ "name": "maxClaimFeeMillibps",
+ "type": "u64"
+ },
+ {
+ "name": "pauseAuthority",
+ "type": "publicKey"
+ },
+ {
+ "name": "isPaused",
+ "type": "bool"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Quarry",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "rewarderKey",
+ "type": "publicKey"
+ },
+ {
+ "name": "tokenMintKey",
+ "type": "publicKey"
+ },
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "index",
+ "type": "u16"
+ },
+ {
+ "name": "tokenMintDecimals",
+ "type": "u8"
+ },
+ {
+ "name": "famineTs",
+ "type": "i64"
+ },
+ {
+ "name": "lastUpdateTs",
+ "type": "i64"
+ },
+ {
+ "name": "rewardsPerTokenStored",
+ "type": "u128"
+ },
+ {
+ "name": "annualRewardsRate",
+ "type": "u64"
+ },
+ {
+ "name": "rewardsShare",
+ "type": "u64"
+ },
+ {
+ "name": "totalTokensDeposited",
+ "type": "u64"
+ },
+ {
+ "name": "numMiners",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Miner",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "quarryKey",
+ "type": "publicKey"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "tokenVaultKey",
+ "type": "publicKey"
+ },
+ {
+ "name": "rewardsEarned",
+ "type": "u64"
+ },
+ {
+ "name": "rewardsPerTokenPaid",
+ "type": "u128"
+ },
+ {
+ "name": "balance",
+ "type": "u64"
+ },
+ {
+ "name": "index",
+ "type": "u64"
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "StakeAction",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Stake"
+ },
+ {
+ "name": "Withdraw"
+ }
+ ]
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "NewRewarderEvent",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "ClaimEvent",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "stakedToken",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "rewardsToken",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "fees",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "StakeEvent",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "token",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "WithdrawEvent",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "token",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "RewarderAnnualRewardsUpdateEvent",
+ "fields": [
+ {
+ "name": "previousRate",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "newRate",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "MinerCreateEvent",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "quarry",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "miner",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "QuarryCreateEvent",
+ "fields": [
+ {
+ "name": "tokenMint",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "QuarryRewardsUpdateEvent",
+ "fields": [
+ {
+ "name": "tokenMint",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "annualRewardsRate",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "rewardsShare",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ }
+ ],
+ "errors": [
+ {
+ "code": 300,
+ "name": "Unauthorized",
+ "msg": "You are not authorized to perform this action."
+ },
+ {
+ "code": 301,
+ "name": "InsufficientBalance",
+ "msg": "Insufficient staked balance for withdraw request."
+ },
+ {
+ "code": 302,
+ "name": "PendingAuthorityNotSet",
+ "msg": "Pending authority not set"
+ },
+ {
+ "code": 303,
+ "name": "InvalidRewardsShare",
+ "msg": "Invalid quarry rewards share"
+ },
+ {
+ "code": 304,
+ "name": "InsufficientAllowance",
+ "msg": "Insufficient allowance."
+ },
+ {
+ "code": 305,
+ "name": "NewVaultNotEmpty",
+ "msg": "New vault not empty."
+ },
+ {
+ "code": 306,
+ "name": "NotEnoughTokens",
+ "msg": "Not enough tokens."
+ },
+ {
+ "code": 307,
+ "name": "InvalidTimestamp",
+ "msg": "Invalid timestamp."
+ },
+ {
+ "code": 308,
+ "name": "InvalidMaxClaimFee",
+ "msg": "Invalid max claim fee."
+ },
+ {
+ "code": 309,
+ "name": "MaxAnnualRewardsRateExceeded",
+ "msg": "Max annual rewards rate exceeded."
+ },
+ {
+ "code": 310,
+ "name": "Paused",
+ "msg": "Rewarder is paused."
+ },
+ {
+ "code": 311,
+ "name": "UpperboundExceeded",
+ "msg": "Rewards earned exceeded quarry's upper bound."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/sol_cerberus.json b/basics/anchorpy-main/tests/idls/sol_cerberus.json
new file mode 100644
index 0000000..5c4cbdc
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/sol_cerberus.json
@@ -0,0 +1,1464 @@
+{
+ "version": "0.1.7",
+ "name": "sol_cerberus",
+ "instructions": [
+ {
+ "name": "initializeApp",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "app",
+ "isMut": true,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "app"
+ },
+ {
+ "kind": "arg",
+ "type": {
+ "defined": "AppData"
+ },
+ "path": "app_data.id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "appData",
+ "type": {
+ "defined": "AppData"
+ }
+ }
+ ]
+ },
+ {
+ "name": "updateApp",
+ "accounts": [
+ {
+ "name": "signer",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "app",
+ "isMut": true,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "app"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "App",
+ "path": "app.id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "appData",
+ "type": {
+ "defined": "UpdateAppData"
+ }
+ }
+ ]
+ },
+ {
+ "name": "deleteApp",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "app",
+ "isMut": true,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "app"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "App",
+ "path": "app.id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "collector",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "addRule",
+ "accounts": [
+ {
+ "name": "signer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "rule",
+ "isMut": true,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "arg",
+ "type": {
+ "defined": "RuleData"
+ },
+ "path": "rule_data.namespace"
+ },
+ {
+ "kind": "arg",
+ "type": {
+ "defined": "RuleData"
+ },
+ "path": "rule_data.role"
+ },
+ {
+ "kind": "arg",
+ "type": {
+ "defined": "RuleData"
+ },
+ "path": "rule_data.resource"
+ },
+ {
+ "kind": "arg",
+ "type": {
+ "defined": "RuleData"
+ },
+ "path": "rule_data.permission"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "App",
+ "path": "sol_cerberus_app.id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusApp",
+ "isMut": false,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "app"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "App",
+ "path": "sol_cerberus_app.id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusRole",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusRule",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "account",
+ "type": "u8",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.namespace"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.role"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.resource"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.permission"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.app_id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusRule2",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "account",
+ "type": "u8",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.namespace"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.role"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.resource"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.permission"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.app_id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusToken",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusMetadata",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusSeed",
+ "isMut": true,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "seed"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "path": "signer"
+ }
+ ]
+ }
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "ruleData",
+ "type": {
+ "defined": "RuleData"
+ }
+ }
+ ]
+ },
+ {
+ "name": "deleteRule",
+ "accounts": [
+ {
+ "name": "signer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "rule",
+ "isMut": true,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "account",
+ "type": "u8",
+ "account": "Rule",
+ "path": "rule.namespace"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "rule.role"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "rule.resource"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "rule.permission"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "App",
+ "path": "sol_cerberus_app.id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusApp",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "solCerberusRole",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusRule",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "account",
+ "type": "u8",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.namespace"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.role"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.resource"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.permission"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.app_id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusRule2",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "account",
+ "type": "u8",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.namespace"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.role"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.resource"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.permission"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "Rule",
+ "path": "sol_cerberus_rule2.app_id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusToken",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusMetadata",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusSeed",
+ "isMut": true,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "seed"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "path": "signer"
+ }
+ ]
+ }
+ },
+ {
+ "name": "collector",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "assignRole",
+ "accounts": [
+ {
+ "name": "signer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "role",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "solCerberusApp",
+ "isMut": false,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "app"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "App",
+ "path": "sol_cerberus_app.id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusRole",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusRule",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "account",
+ "type": "u8",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.namespace"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.role"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.resource"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.permission"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.app_id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusToken",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusMetadata",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusSeed",
+ "isMut": true,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "seed"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "path": "signer"
+ }
+ ]
+ }
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "assignRoleData",
+ "type": {
+ "defined": "AssignRoleData"
+ }
+ }
+ ]
+ },
+ {
+ "name": "deleteAssignedRole",
+ "accounts": [
+ {
+ "name": "signer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "role",
+ "isMut": true,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Role",
+ "path": "role.role"
+ },
+ {
+ "kind": "account",
+ "type": {
+ "option": "publicKey"
+ },
+ "account": "Role",
+ "path": "role.address"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "App",
+ "path": "sol_cerberus_app.id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusApp",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "solCerberusRole",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusRule",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "account",
+ "type": "u8",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.namespace"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.role"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.resource"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.permission"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.app_id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusToken",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusMetadata",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusSeed",
+ "isMut": true,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "seed"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "path": "signer"
+ }
+ ]
+ }
+ },
+ {
+ "name": "collector",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "updateCache",
+ "docs": [
+ "* Updates either app.roles_updated_at or app.rules_updated_at fields, so clients\n * can keep track and cache roles & rules accordingly."
+ ],
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "app",
+ "isMut": true,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "app"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "App",
+ "path": "app.id"
+ }
+ ]
+ },
+ "relations": [
+ "authority"
+ ]
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "cacheUpdated",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "allowed",
+ "docs": [
+ "* Checks if the current user is authorized to run the instruction,\n * throwing \"Unauthorized\" error otherwise."
+ ],
+ "accounts": [
+ {
+ "name": "signer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "solCerberusApp",
+ "isMut": false,
+ "isSigner": false,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "app"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "App",
+ "path": "sol_cerberus_app.id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusRule",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "account",
+ "type": "u8",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.namespace"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.role"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.resource"
+ },
+ {
+ "kind": "account",
+ "type": "string",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.permission"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "account": "Rule",
+ "path": "sol_cerberus_rule.app_id"
+ }
+ ]
+ }
+ },
+ {
+ "name": "solCerberusRole",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusToken",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusMetadata",
+ "isMut": false,
+ "isSigner": false,
+ "isOptional": true
+ },
+ {
+ "name": "solCerberusSeed",
+ "isMut": true,
+ "isSigner": false,
+ "isOptional": true,
+ "pda": {
+ "seeds": [
+ {
+ "kind": "const",
+ "type": "string",
+ "value": "seed"
+ },
+ {
+ "kind": "account",
+ "type": "publicKey",
+ "path": "signer"
+ }
+ ]
+ }
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "allowedRule",
+ "type": {
+ "defined": "AllowedRule"
+ }
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "App",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "id",
+ "type": "publicKey"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "recovery",
+ "type": {
+ "option": "publicKey"
+ }
+ },
+ {
+ "name": "bump",
+ "type": "u8"
+ },
+ {
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "name": "rolesUpdatedAt",
+ "type": "i64"
+ },
+ {
+ "name": "rulesUpdatedAt",
+ "type": "i64"
+ },
+ {
+ "name": "cached",
+ "type": "bool"
+ },
+ {
+ "name": "fee",
+ "type": {
+ "option": "u64"
+ }
+ },
+ {
+ "name": "class",
+ "type": "u8"
+ },
+ {
+ "name": "expiresAt",
+ "type": {
+ "option": "i64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Seed",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "initialized",
+ "type": "bool"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Role",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "appId",
+ "type": "publicKey"
+ },
+ {
+ "name": "address",
+ "type": {
+ "option": "publicKey"
+ }
+ },
+ {
+ "name": "role",
+ "type": "string"
+ },
+ {
+ "name": "addressType",
+ "type": {
+ "defined": "AddressType"
+ }
+ },
+ {
+ "name": "expiresAt",
+ "type": {
+ "option": "i64"
+ }
+ },
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Rule",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "appId",
+ "type": "publicKey"
+ },
+ {
+ "name": "namespace",
+ "type": "u8"
+ },
+ {
+ "name": "role",
+ "type": "string"
+ },
+ {
+ "name": "resource",
+ "type": "string"
+ },
+ {
+ "name": "permission",
+ "type": "string"
+ },
+ {
+ "name": "expiresAt",
+ "type": {
+ "option": "i64"
+ }
+ },
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "AllowedRule",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "appId",
+ "type": "publicKey"
+ },
+ {
+ "name": "namespace",
+ "type": "u8"
+ },
+ {
+ "name": "resource",
+ "type": "string"
+ },
+ {
+ "name": "permission",
+ "type": "string"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AppData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "id",
+ "type": "publicKey"
+ },
+ {
+ "name": "recovery",
+ "type": {
+ "option": "publicKey"
+ }
+ },
+ {
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "name": "cached",
+ "type": "bool"
+ }
+ ]
+ }
+ },
+ {
+ "name": "UpdateAppData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "recovery",
+ "type": {
+ "option": "publicKey"
+ }
+ },
+ {
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "name": "cached",
+ "type": "bool"
+ },
+ {
+ "name": "fee",
+ "type": {
+ "option": "u64"
+ }
+ },
+ {
+ "name": "class",
+ "type": "u8"
+ },
+ {
+ "name": "expiresAt",
+ "type": {
+ "option": "i64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "AssignRoleData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "address",
+ "type": {
+ "option": "publicKey"
+ }
+ },
+ {
+ "name": "role",
+ "type": "string"
+ },
+ {
+ "name": "addressType",
+ "type": {
+ "defined": "AddressType"
+ }
+ },
+ {
+ "name": "expiresAt",
+ "type": {
+ "option": "i64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "RuleData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "namespace",
+ "type": "u8"
+ },
+ {
+ "name": "role",
+ "type": "string"
+ },
+ {
+ "name": "resource",
+ "type": "string"
+ },
+ {
+ "name": "permission",
+ "type": "string"
+ },
+ {
+ "name": "expiresAt",
+ "type": {
+ "option": "i64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Classes",
+ "docs": [
+ "Classes:",
+ "0 => Trial (Apps with default fees)",
+ "1 => Free (Apps with no fees)"
+ ],
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Trial"
+ },
+ {
+ "name": "Free"
+ }
+ ]
+ }
+ },
+ {
+ "name": "CacheUpdated",
+ "docs": [
+ "CacheUpdated:",
+ "0 => Roles (When roles change)",
+ "1 => Rules (When rules change)"
+ ],
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Roles"
+ },
+ {
+ "name": "Rules"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AddressType",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Wallet"
+ },
+ {
+ "name": "Nft"
+ },
+ {
+ "name": "Collection"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Namespaces",
+ "docs": [
+ "Namespaces:",
+ "0 => Rule (Normal permissions)",
+ "1 => AssignRole (White list of roles that can be assigned by certain role)",
+ "2 => DeleteAssignRole (White list of roles that can be deleted by certain role)",
+ "3 => AddRuleNSRole (White list of namespaces and roles that can be created by certain role)",
+ "4 => AddRuleResourcePerm (White list of resources and permissions that can be created by certain role)",
+ "5 => DeleteRuleNSRole (White list of namespaces and roles that can be deleted by certain role)",
+ "6 => DeleteRuleResourcePerm (White list of resources and permissions that can be deleted by certain role)"
+ ],
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Rule"
+ },
+ {
+ "name": "AssignRole"
+ },
+ {
+ "name": "DeleteAssignRole"
+ },
+ {
+ "name": "AddRuleNSRole"
+ },
+ {
+ "name": "AddRuleResourcePerm"
+ },
+ {
+ "name": "DeleteRuleNSRole"
+ },
+ {
+ "name": "DeleteRuleResourcePerm"
+ }
+ ]
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "AppChanged",
+ "fields": [
+ {
+ "name": "time",
+ "type": "i64",
+ "index": false
+ },
+ {
+ "name": "appId",
+ "type": "publicKey",
+ "index": true
+ },
+ {
+ "name": "authority",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "RolesChanged",
+ "fields": [
+ {
+ "name": "time",
+ "type": "i64",
+ "index": false
+ },
+ {
+ "name": "appId",
+ "type": "publicKey",
+ "index": true
+ }
+ ]
+ },
+ {
+ "name": "RulesChanged",
+ "fields": [
+ {
+ "name": "time",
+ "type": "i64",
+ "index": false
+ },
+ {
+ "name": "appId",
+ "type": "publicKey",
+ "index": true
+ }
+ ]
+ }
+ ],
+ "errors": [
+ {
+ "code": 6000,
+ "name": "UnauthorizedAuthorityUpdate",
+ "msg": "Only current Authority or Recovery accounts can update the App authority"
+ },
+ {
+ "code": 6001,
+ "name": "InvalidRule",
+ "msg": "Role, Resource or Permission must be betwen 1 and 16 alphanumeric characters long"
+ },
+ {
+ "code": 6002,
+ "name": "InvalidRole",
+ "msg": "Role must be between 1 and 16 alphanumeric characters long"
+ },
+ {
+ "code": 6003,
+ "name": "StringTooShort",
+ "msg": "The provided string is too short"
+ },
+ {
+ "code": 6004,
+ "name": "StringTooLong",
+ "msg": "The provided string is too long"
+ },
+ {
+ "code": 6005,
+ "name": "Unauthorized",
+ "msg": "The user does not have enough privileges to perform this action"
+ },
+ {
+ "code": 6006,
+ "name": "InvalidAppID",
+ "msg": "The Sol Cerberus APP ID does not match the one defined in the program"
+ },
+ {
+ "code": 6007,
+ "name": "InvalidAddressType",
+ "msg": "Invalid address type, mus be either 'Wallet', 'Nft', 'Collection' or a wildcard '*'"
+ },
+ {
+ "code": 6008,
+ "name": "InvalidNamespace",
+ "msg": "Invalid namespace, must be either an u8 number (0-255) or a wildcard '*'"
+ },
+ {
+ "code": 6009,
+ "name": "MissingSolCerberusAppId",
+ "msg": "SOL_CERBERUS_APP_ID is missing on lib.rs"
+ },
+ {
+ "code": 6010,
+ "name": "MissingSeedAccount",
+ "msg": "The Sol Cerberus Seed account is missing"
+ },
+ {
+ "code": 6011,
+ "name": "UnauthorizedProgramAuthority",
+ "msg": "Only program authority can perform this action"
+ },
+ {
+ "code": 6012,
+ "name": "InsufficientFunds",
+ "msg": "Insufficient funds for transaction"
+ }
+ ],
+ "metadata": {
+ "address": "SCERbrcgSPwgkrJ7j4TABr17dhYzdgiwPZUSSfFPt8x"
+ }
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/spl_token.json b/basics/anchorpy-main/tests/idls/spl_token.json
new file mode 100644
index 0000000..773e470
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/spl_token.json
@@ -0,0 +1,844 @@
+{
+ "version": "3.3.0",
+ "name": "spl_token",
+ "instructions": [
+ {
+ "name": "initializeMint",
+ "accounts": [
+ {
+ "name": "mint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "decimals",
+ "type": "u8"
+ },
+ {
+ "name": "mintAuthority",
+ "type": "publicKey"
+ },
+ {
+ "name": "freezeAuthority",
+ "type": {
+ "defined": "COption"
+ }
+ }
+ ]
+ },
+ {
+ "name": "initializeAccount",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "initializeMultisig",
+ "accounts": [
+ {
+ "name": "multisig",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "m",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "transfer",
+ "accounts": [
+ {
+ "name": "source",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "destination",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "approve",
+ "accounts": [
+ {
+ "name": "source",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "delegate",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "revoke",
+ "accounts": [
+ {
+ "name": "source",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "setAuthority",
+ "accounts": [
+ {
+ "name": "owned",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "signer",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "authorityType",
+ "type": {
+ "defined": "AuthorityType"
+ }
+ },
+ {
+ "name": "newAuthority",
+ "type": {
+ "defined": "COption"
+ }
+ }
+ ]
+ },
+ {
+ "name": "mintTo",
+ "accounts": [
+ {
+ "name": "mint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "burn",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "closeAccount",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "destination",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "freezeAccount",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "thawAccount",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "transferChecked",
+ "accounts": [
+ {
+ "name": "source",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "destination",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "decimals",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "approveChecked",
+ "accounts": [
+ {
+ "name": "source",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "delegate",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "decimals",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "mintToChecked",
+ "accounts": [
+ {
+ "name": "mint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "decimals",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "burnChecked",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "decimals",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "initializeAccount2",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "owner",
+ "type": "publicKey"
+ }
+ ]
+ },
+ {
+ "name": "syncNative",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "initializeAccount3",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "owner",
+ "type": "publicKey"
+ }
+ ]
+ },
+ {
+ "name": "initializeMultisig2",
+ "accounts": [
+ {
+ "name": "multisig",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "signer",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "m",
+ "type": "u8"
+ }
+ ]
+ },
+ {
+ "name": "initializeMint2",
+ "accounts": [
+ {
+ "name": "mint",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "decimals",
+ "type": "u8"
+ },
+ {
+ "name": "mintAuthority",
+ "type": "publicKey"
+ },
+ {
+ "name": "freezeAuthority",
+ "type": {
+ "defined": "COption"
+ }
+ }
+ ]
+ },
+ {
+ "name": "getAccountDataSize",
+ "accounts": [
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "initializeImmutableOwner",
+ "accounts": [
+ {
+ "name": "account",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ },
+ {
+ "name": "amountToUiAmount",
+ "accounts": [
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "uiAmountToAmount",
+ "accounts": [
+ {
+ "name": "mint",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "uiAmount",
+ "type": {
+ "defined": "&'astr"
+ }
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Mint",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "mintAuthority",
+ "type": {
+ "defined": "COption"
+ }
+ },
+ {
+ "name": "supply",
+ "type": "u64"
+ },
+ {
+ "name": "decimals",
+ "type": "u8"
+ },
+ {
+ "name": "isInitialized",
+ "type": "bool"
+ },
+ {
+ "name": "freezeAuthority",
+ "type": {
+ "defined": "COption"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Account",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "mint",
+ "type": "publicKey"
+ },
+ {
+ "name": "owner",
+ "type": "publicKey"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "delegate",
+ "type": {
+ "defined": "COption"
+ }
+ },
+ {
+ "name": "state",
+ "type": {
+ "defined": "AccountState"
+ }
+ },
+ {
+ "name": "isNative",
+ "type": {
+ "defined": "COption"
+ }
+ },
+ {
+ "name": "delegatedAmount",
+ "type": "u64"
+ },
+ {
+ "name": "closeAuthority",
+ "type": {
+ "defined": "COption"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Multisig",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "m",
+ "type": "u8"
+ },
+ {
+ "name": "n",
+ "type": "u8"
+ },
+ {
+ "name": "isInitialized",
+ "type": "bool"
+ },
+ {
+ "name": "signers",
+ "type": {
+ "array": [
+ "publicKey",
+ 11
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "AccountState",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Uninitialized"
+ },
+ {
+ "name": "Initialized"
+ },
+ {
+ "name": "Frozen"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AuthorityType",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "MintTokens"
+ },
+ {
+ "name": "FreezeAccount"
+ },
+ {
+ "name": "AccountOwner"
+ },
+ {
+ "name": "CloseAccount"
+ }
+ ]
+ }
+ }
+ ],
+ "errors": [
+ {
+ "code": 0,
+ "name": "NotRentExempt",
+ "msg": "Lamport balance below rent-exempt threshold"
+ },
+ {
+ "code": 1,
+ "name": "InsufficientFunds",
+ "msg": "Insufficient funds"
+ },
+ {
+ "code": 2,
+ "name": "InvalidMint",
+ "msg": "Invalid Mint"
+ },
+ {
+ "code": 3,
+ "name": "MintMismatch",
+ "msg": "Account not associated with this Mint"
+ },
+ {
+ "code": 4,
+ "name": "OwnerMismatch",
+ "msg": "Owner does not match"
+ },
+ {
+ "code": 5,
+ "name": "FixedSupply",
+ "msg": "Fixed supply"
+ },
+ {
+ "code": 6,
+ "name": "AlreadyInUse",
+ "msg": "Already in use"
+ },
+ {
+ "code": 7,
+ "name": "InvalidNumberOfProvidedSigners",
+ "msg": "Invalid number of provided signers"
+ },
+ {
+ "code": 8,
+ "name": "InvalidNumberOfRequiredSigners",
+ "msg": "Invalid number of required signers"
+ },
+ {
+ "code": 9,
+ "name": "UninitializedState",
+ "msg": "State is unititialized"
+ },
+ {
+ "code": 10,
+ "name": "NativeNotSupported",
+ "msg": "Instruction does not support native tokens"
+ },
+ {
+ "code": 11,
+ "name": "NonNativeHasBalance",
+ "msg": "Non-native account can only be closed if its balance is zero"
+ },
+ {
+ "code": 12,
+ "name": "InvalidInstruction",
+ "msg": "Invalid instruction"
+ },
+ {
+ "code": 13,
+ "name": "InvalidState",
+ "msg": "State is invalid for requested operation"
+ },
+ {
+ "code": 14,
+ "name": "Overflow",
+ "msg": "Operation overflowed"
+ },
+ {
+ "code": 15,
+ "name": "AuthorityTypeNotSupported",
+ "msg": "Account does not support specified authority type"
+ },
+ {
+ "code": 16,
+ "name": "MintCannotFreeze",
+ "msg": "This token mint cannot freeze accounts"
+ },
+ {
+ "code": 17,
+ "name": "AccountFrozen",
+ "msg": "Account is frozen"
+ },
+ {
+ "code": 18,
+ "name": "MintDecimalsMismatch",
+ "msg": "The provided decimals value different from the Mint decimals"
+ },
+ {
+ "code": 19,
+ "name": "NonNativeNotSupported",
+ "msg": "Instruction does not support non-native tokens"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/swap.json b/basics/anchorpy-main/tests/idls/swap.json
new file mode 100644
index 0000000..6ea31d0
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/swap.json
@@ -0,0 +1,352 @@
+{
+ "version": "0.0.0",
+ "name": "swap",
+ "instructions": [
+ {
+ "name": "swap",
+ "accounts": [
+ {
+ "name": "market",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "openOrders",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "requestQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "eventQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "bids",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "asks",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "orderPayerTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "coinVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "pcVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vaultSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "coinWallet",
+ "isMut": true,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "pcWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "dexProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "side",
+ "type": {
+ "defined": "Side"
+ }
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "minExpectedSwapAmount",
+ "type": "u64"
+ }
+ ]
+ },
+ {
+ "name": "swapTransitive",
+ "accounts": [
+ {
+ "name": "from",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "openOrders",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "requestQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "eventQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "bids",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "asks",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "orderPayerTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "coinVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "pcVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vaultSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "coinWallet",
+ "isMut": true,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "to",
+ "accounts": [
+ {
+ "name": "market",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "openOrders",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "requestQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "eventQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "bids",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "asks",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "orderPayerTokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "coinVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "pcVault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vaultSigner",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "coinWallet",
+ "isMut": true,
+ "isSigner": false
+ }
+ ]
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "pcWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "dexProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "amount",
+ "type": "u64"
+ },
+ {
+ "name": "minExpectedSwapAmount",
+ "type": "u64"
+ }
+ ]
+ }
+ ],
+ "types": [
+ {
+ "name": "Side",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Bid"
+ },
+ {
+ "name": "Ask"
+ }
+ ]
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "DidSwap",
+ "fields": [
+ {
+ "name": "givenAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "minExpectedSwapAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "fromAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "toAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "spillAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "fromMint",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "toMint",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "quoteMint",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "authority",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ }
+ ],
+ "errors": [
+ {
+ "code": 300,
+ "name": "SwapTokensCannotMatch",
+ "msg": "The tokens being swapped must have different mints"
+ },
+ {
+ "code": 301,
+ "name": "SlippageExceeded",
+ "msg": "Slippage tolerance exceeded"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/switchboard.json b/basics/anchorpy-main/tests/idls/switchboard.json
new file mode 100644
index 0000000..c476c4a
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/switchboard.json
@@ -0,0 +1 @@
+{"version": "0.1.0", "name": "switchboard_v2", "instructions": [{"name": "vaultTransfer", "accounts": [{"name": "state", "isMut": false, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}, {"name": "to", "isMut": true, "isSigner": false}, {"name": "vault", "isMut": true, "isSigner": false}, {"name": "tokenProgram", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "VaultTransferParams"}}]}, {"name": "programInit", "accounts": [{"name": "state", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": false}, {"name": "tokenMint", "isMut": true, "isSigner": false}, {"name": "vault", "isMut": true, "isSigner": false}, {"name": "payer", "isMut": true, "isSigner": false}, {"name": "systemProgram", "isMut": false, "isSigner": false}, {"name": "tokenProgram", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "ProgramInitParams"}}]}, {"name": "programConfig", "accounts": [{"name": "authority", "isMut": false, "isSigner": true}, {"name": "programState", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "ProgramConfigParams"}}]}, {"name": "aggregatorInit", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": false}, {"name": "queue", "isMut": false, "isSigner": false}, {"name": "authorWallet", "isMut": false, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "AggregatorInitParams"}}]}, {"name": "aggregatorLock", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": true, "isSigner": true}], "args": [{"name": "params", "type": {"defined": "AggregatorLockParams"}}]}, {"name": "aggregatorSetAuthority", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}, {"name": "newAuthority", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "AggregatorSetAuthorityParams"}}]}, {"name": "aggregatorSetBatchSize", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}], "args": [{"name": "params", "type": {"defined": "AggregatorSetBatchSizeParams"}}]}, {"name": "aggregatorSetMinJobs", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}], "args": [{"name": "params", "type": {"defined": "AggregatorSetMinJobsParams"}}]}, {"name": "aggregatorSetMinOracles", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}], "args": [{"name": "params", "type": {"defined": "AggregatorSetMinOraclesParams"}}]}, {"name": "aggregatorSetVarianceThreshold", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}], "args": [{"name": "params", "type": {"defined": "AggregatorSetVarianceThresholdParams"}}]}, {"name": "aggregatorSetHistoryBuffer", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}, {"name": "buffer", "isMut": true, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "AggregatorSetHistoryBufferParams"}}]}, {"name": "aggregatorSetQueue", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}, {"name": "queue", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "AggregatorSetQueueParams"}}]}, {"name": "aggregatorAddJob", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}, {"name": "job", "isMut": true, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "AggregatorAddJobParams"}}]}, {"name": "aggregatorRemoveJob", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}, {"name": "job", "isMut": true, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "AggregatorRemoveJobParams"}}]}, {"name": "aggregatorOpenRound", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "lease", "isMut": true, "isSigner": false}, {"name": "oracleQueue", "isMut": true, "isSigner": false}, {"name": "queueAuthority", "isMut": false, "isSigner": false}, {"name": "permission", "isMut": true, "isSigner": false}, {"name": "escrow", "isMut": true, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}, {"name": "payoutWallet", "isMut": true, "isSigner": false}, {"name": "tokenProgram", "isMut": false, "isSigner": false}, {"name": "dataBuffer", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "AggregatorOpenRoundParams"}}]}, {"name": "aggregatorSaveResult", "accounts": [{"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "oracle", "isMut": true, "isSigner": false}, {"name": "oracleAuthority", "isMut": false, "isSigner": true}, {"name": "oracleQueue", "isMut": false, "isSigner": false}, {"name": "queueAuthority", "isMut": false, "isSigner": false}, {"name": "feedPermission", "isMut": true, "isSigner": false}, {"name": "oraclePermission", "isMut": false, "isSigner": false}, {"name": "lease", "isMut": true, "isSigner": false}, {"name": "escrow", "isMut": true, "isSigner": false}, {"name": "tokenProgram", "isMut": false, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}, {"name": "historyBuffer", "isMut": true, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "AggregatorSaveResultParams"}}]}, {"name": "jobInit", "accounts": [{"name": "job", "isMut": true, "isSigner": false}, {"name": "authorWallet", "isMut": false, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "JobInitParams"}}]}, {"name": "permissionInit", "accounts": [{"name": "permission", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": false}, {"name": "granter", "isMut": false, "isSigner": false}, {"name": "grantee", "isMut": false, "isSigner": false}, {"name": "payer", "isMut": true, "isSigner": true}, {"name": "systemProgram", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "PermissionInitParams"}}]}, {"name": "permissionSet", "accounts": [{"name": "permission", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}], "args": [{"name": "params", "type": {"defined": "PermissionSetParams"}}]}, {"name": "oracleQueueInit", "accounts": [{"name": "oracleQueue", "isMut": true, "isSigner": true}, {"name": "authority", "isMut": false, "isSigner": false}, {"name": "buffer", "isMut": true, "isSigner": false}, {"name": "payer", "isMut": true, "isSigner": false}, {"name": "systemProgram", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "OracleQueueInitParams"}}]}, {"name": "oracleQueueSetRewards", "accounts": [{"name": "queue", "isMut": true, "isSigner": false}, {"name": "authority", "isMut": false, "isSigner": true}], "args": [{"name": "params", "type": {"defined": "OracleQueueSetRewardsParams"}}]}, {"name": "oracleInit", "accounts": [{"name": "oracle", "isMut": true, "isSigner": false}, {"name": "oracleAuthority", "isMut": false, "isSigner": false}, {"name": "wallet", "isMut": false, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}, {"name": "queue", "isMut": false, "isSigner": false}, {"name": "payer", "isMut": false, "isSigner": false}, {"name": "systemProgram", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "OracleInitParams"}}]}, {"name": "oracleHeartbeat", "accounts": [{"name": "oracle", "isMut": true, "isSigner": false}, {"name": "oracleAuthority", "isMut": false, "isSigner": true}, {"name": "tokenAccount", "isMut": false, "isSigner": false}, {"name": "gcOracle", "isMut": true, "isSigner": false}, {"name": "oracleQueue", "isMut": true, "isSigner": false}, {"name": "permission", "isMut": false, "isSigner": false}, {"name": "dataBuffer", "isMut": true, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "OracleHeartbeatParams"}}]}, {"name": "oracleWithdraw", "accounts": [{"name": "oracle", "isMut": true, "isSigner": false}, {"name": "oracleAuthority", "isMut": false, "isSigner": true}, {"name": "tokenAccount", "isMut": true, "isSigner": false}, {"name": "withdrawAccount", "isMut": true, "isSigner": false}, {"name": "oracleQueue", "isMut": true, "isSigner": false}, {"name": "permission", "isMut": true, "isSigner": false}, {"name": "tokenProgram", "isMut": false, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}, {"name": "payer", "isMut": true, "isSigner": true}, {"name": "systemProgram", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "OracleWithdrawParams"}}]}, {"name": "leaseInit", "accounts": [{"name": "lease", "isMut": true, "isSigner": false}, {"name": "queue", "isMut": true, "isSigner": false}, {"name": "aggregator", "isMut": false, "isSigner": false}, {"name": "funder", "isMut": true, "isSigner": false}, {"name": "payer", "isMut": true, "isSigner": true}, {"name": "systemProgram", "isMut": false, "isSigner": false}, {"name": "tokenProgram", "isMut": false, "isSigner": false}, {"name": "owner", "isMut": true, "isSigner": true}, {"name": "escrow", "isMut": true, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "LeaseInitParams"}}]}, {"name": "leaseExtend", "accounts": [{"name": "lease", "isMut": true, "isSigner": false}, {"name": "aggregator", "isMut": false, "isSigner": false}, {"name": "queue", "isMut": false, "isSigner": false}, {"name": "funder", "isMut": true, "isSigner": false}, {"name": "owner", "isMut": true, "isSigner": true}, {"name": "escrow", "isMut": true, "isSigner": false}, {"name": "tokenProgram", "isMut": false, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "LeaseExtendParams"}}]}, {"name": "leaseWithdraw", "accounts": [{"name": "lease", "isMut": true, "isSigner": false}, {"name": "escrow", "isMut": true, "isSigner": false}, {"name": "aggregator", "isMut": false, "isSigner": false}, {"name": "queue", "isMut": false, "isSigner": false}, {"name": "withdrawAuthority", "isMut": false, "isSigner": true}, {"name": "withdrawAccount", "isMut": true, "isSigner": false}, {"name": "tokenProgram", "isMut": false, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "LeaseWithdrawParams"}}]}, {"name": "crankInit", "accounts": [{"name": "crank", "isMut": true, "isSigner": true}, {"name": "queue", "isMut": false, "isSigner": false}, {"name": "buffer", "isMut": true, "isSigner": false}, {"name": "payer", "isMut": true, "isSigner": false}, {"name": "systemProgram", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "CrankInitParams"}}]}, {"name": "crankPush", "accounts": [{"name": "crank", "isMut": true, "isSigner": false}, {"name": "aggregator", "isMut": true, "isSigner": false}, {"name": "oracleQueue", "isMut": true, "isSigner": false}, {"name": "queueAuthority", "isMut": false, "isSigner": false}, {"name": "permission", "isMut": false, "isSigner": false}, {"name": "lease", "isMut": true, "isSigner": false}, {"name": "escrow", "isMut": true, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}, {"name": "dataBuffer", "isMut": true, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "CrankPushParams"}}]}, {"name": "crankPop", "accounts": [{"name": "crank", "isMut": true, "isSigner": false}, {"name": "oracleQueue", "isMut": true, "isSigner": false}, {"name": "queueAuthority", "isMut": false, "isSigner": false}, {"name": "programState", "isMut": false, "isSigner": false}, {"name": "payoutWallet", "isMut": true, "isSigner": false}, {"name": "tokenProgram", "isMut": false, "isSigner": false}, {"name": "crankDataBuffer", "isMut": true, "isSigner": false}, {"name": "queueDataBuffer", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "CrankPopParams"}}]}, {"name": "ecvrfVerify", "accounts": [{"name": "randomnessProducer", "isMut": false, "isSigner": false}], "args": [{"name": "params", "type": {"defined": "EcvrfVerifyParams"}}]}], "accounts": [{"name": "SbState", "type": {"kind": "struct", "fields": [{"name": "authority", "type": "publicKey"}, {"name": "tokenMint", "type": "publicKey"}, {"name": "tokenVault", "type": "publicKey"}, {"name": "ebuf", "type": {"array": ["u8", 1024]}}]}}, {"name": "AggregatorAccountData", "type": {"kind": "struct", "fields": [{"name": "name", "type": {"array": ["u8", 32]}}, {"name": "metadata", "type": {"array": ["u8", 128]}}, {"name": "authorWallet", "type": "publicKey"}, {"name": "queuePubkey", "type": "publicKey"}, {"name": "oracleRequestBatchSize", "type": "u32"}, {"name": "minOracleResults", "type": "u32"}, {"name": "minJobResults", "type": "u32"}, {"name": "minUpdateDelaySeconds", "type": "u32"}, {"name": "startAfter", "type": "i64"}, {"name": "varianceThreshold", "type": {"defined": "SwitchboardDecimal"}}, {"name": "forceReportPeriod", "type": "i64"}, {"name": "expiration", "type": "i64"}, {"name": "consecutiveFailureCount", "type": "u64"}, {"name": "nextAllowedUpdateTime", "type": "i64"}, {"name": "isLocked", "type": "bool"}, {"name": "crankPubkey", "type": "publicKey"}, {"name": "latestConfirmedRound", "type": {"defined": "AggregatorRound"}}, {"name": "currentRound", "type": {"defined": "AggregatorRound"}}, {"name": "jobPubkeysData", "type": {"array": ["publicKey", 16]}}, {"name": "jobHashes", "type": {"array": [{"defined": "Hash"}, 16]}}, {"name": "jobPubkeysSize", "type": "u32"}, {"name": "jobsChecksum", "type": {"array": ["u8", 32]}}, {"name": "authority", "type": "publicKey"}, {"name": "historyBuffer", "type": "publicKey"}, {"name": "ebuf", "type": {"array": ["u8", 192]}}]}}, {"name": "PermissionAccountData", "type": {"kind": "struct", "fields": [{"name": "authority", "type": "publicKey"}, {"name": "permissions", "type": "u32"}, {"name": "granter", "type": "publicKey"}, {"name": "grantee", "type": "publicKey"}, {"name": "expiration", "type": "i64"}, {"name": "ebuf", "type": {"array": ["u8", 256]}}]}}, {"name": "LeaseAccountData", "type": {"kind": "struct", "fields": [{"name": "escrow", "type": "publicKey"}, {"name": "queue", "type": "publicKey"}, {"name": "aggregator", "type": "publicKey"}, {"name": "tokenProgram", "type": "publicKey"}, {"name": "isActive", "type": "bool"}, {"name": "crankRowCount", "type": "u32"}, {"name": "createdAt", "type": "i64"}, {"name": "updateCount", "type": "u128"}, {"name": "withdrawAuthority", "type": "publicKey"}, {"name": "ebuf", "type": {"array": ["u8", 256]}}]}}, {"name": "OracleQueueAccountData", "type": {"kind": "struct", "fields": [{"name": "name", "type": {"array": ["u8", 32]}}, {"name": "metadata", "type": {"array": ["u8", 64]}}, {"name": "authority", "type": "publicKey"}, {"name": "oracleTimeout", "type": "u32"}, {"name": "reward", "type": "u64"}, {"name": "minStake", "type": "u64"}, {"name": "slashingEnabled", "type": "bool"}, {"name": "varianceToleranceMultiplier", "type": {"defined": "SwitchboardDecimal"}}, {"name": "feedProbationPeriod", "type": "u32"}, {"name": "currIdx", "type": "u32"}, {"name": "size", "type": "u32"}, {"name": "gcIdx", "type": "u32"}, {"name": "consecutiveFeedFailureLimit", "type": "u64"}, {"name": "consecutiveOracleFailureLimit", "type": "u64"}, {"name": "unpermissionedFeedsEnabled", "type": "bool"}, {"name": "ebuf", "type": {"array": ["u8", 1023]}}, {"name": "maxSize", "type": "u32"}, {"name": "dataBuffer", "type": "publicKey"}]}}, {"name": "CrankAccountData", "type": {"kind": "struct", "fields": [{"name": "name", "type": {"array": ["u8", 32]}}, {"name": "metadata", "type": {"array": ["u8", 64]}}, {"name": "queuePubkey", "type": "publicKey"}, {"name": "pqSize", "type": "u32"}, {"name": "maxRows", "type": "u32"}, {"name": "jitterModifier", "type": "u8"}, {"name": "ebuf", "type": {"array": ["u8", 255]}}, {"name": "dataBuffer", "type": "publicKey"}]}}, {"name": "VrfAccountData", "type": {"kind": "struct", "fields": [{"name": "counter", "type": "u128"}, {"name": "latestFinalizedRound", "type": {"defined": "VrfRound"}}, {"name": "currentRound", "type": {"defined": "VrfRound"}}, {"name": "ebuf", "type": {"array": ["u8", 255]}}]}}, {"name": "OracleAccountData", "type": {"kind": "struct", "fields": [{"name": "name", "type": {"array": ["u8", 32]}}, {"name": "metadata", "type": {"array": ["u8", 128]}}, {"name": "oracleAuthority", "type": "publicKey"}, {"name": "lastHeartbeat", "type": "i64"}, {"name": "numInUse", "type": "u32"}, {"name": "tokenAccount", "type": "publicKey"}, {"name": "queuePubkey", "type": "publicKey"}, {"name": "metrics", "type": {"defined": "OracleMetrics"}}, {"name": "ebuf", "type": {"array": ["u8", 256]}}]}}, {"name": "JobAccountData", "type": {"kind": "struct", "fields": [{"name": "name", "type": {"array": ["u8", 32]}}, {"name": "metadata", "type": {"array": ["u8", 64]}}, {"name": "authorWallet", "type": "publicKey"}, {"name": "expiration", "type": "i64"}, {"name": "hash", "type": {"array": ["u8", 32]}}, {"name": "data", "type": "bytes"}, {"name": "referenceCount", "type": "u32"}]}}], "types": [{"name": "AggregatorAddJobParams", "type": {"kind": "struct", "fields": []}}, {"name": "AggregatorInitParams", "type": {"kind": "struct", "fields": [{"name": "name", "type": {"array": ["u8", 32]}}, {"name": "metadata", "type": {"array": ["u8", 128]}}, {"name": "batchSize", "type": "u32"}, {"name": "minOracleResults", "type": "u32"}, {"name": "minJobResults", "type": "u32"}, {"name": "minUpdateDelaySeconds", "type": "u32"}, {"name": "startAfter", "type": "i64"}, {"name": "varianceThreshold", "type": {"defined": "BorshDecimal"}}, {"name": "forceReportPeriod", "type": "i64"}, {"name": "expiration", "type": "i64"}, {"name": "stateBump", "type": "u8"}]}}, {"name": "AggregatorLockParams", "type": {"kind": "struct", "fields": []}}, {"name": "AggregatorOpenRoundParams", "type": {"kind": "struct", "fields": [{"name": "stateBump", "type": "u8"}, {"name": "leaseBump", "type": "u8"}, {"name": "permissionBump", "type": "u8"}, {"name": "jitter", "type": "u8"}]}}, {"name": "AggregatorRemoveJobParams", "type": {"kind": "struct", "fields": [{"name": "jobIdx", "type": "u32"}]}}, {"name": "AggregatorSaveResultParams", "type": {"kind": "struct", "fields": [{"name": "oracleIdx", "type": "u32"}, {"name": "error", "type": "bool"}, {"name": "value", "type": {"defined": "BorshDecimal"}}, {"name": "jobsChecksum", "type": {"array": ["u8", 32]}}, {"name": "minResponse", "type": {"defined": "BorshDecimal"}}, {"name": "maxResponse", "type": {"defined": "BorshDecimal"}}, {"name": "feedPermissionBump", "type": "u8"}, {"name": "oraclePermissionBump", "type": "u8"}, {"name": "leaseBump", "type": "u8"}, {"name": "stateBump", "type": "u8"}]}}, {"name": "AggregatorSetAuthorityParams", "type": {"kind": "struct", "fields": []}}, {"name": "AggregatorSetBatchSizeParams", "type": {"kind": "struct", "fields": [{"name": "batchSize", "type": "u32"}]}}, {"name": "AggregatorSetHistoryBufferParams", "type": {"kind": "struct", "fields": []}}, {"name": "AggregatorSetMinJobsParams", "type": {"kind": "struct", "fields": [{"name": "minJobResults", "type": "u32"}]}}, {"name": "AggregatorSetMinOraclesParams", "type": {"kind": "struct", "fields": [{"name": "minOracleResults", "type": "u32"}]}}, {"name": "AggregatorSetQueueParams", "type": {"kind": "struct", "fields": []}}, {"name": "AggregatorSetVarianceThresholdParams", "type": {"kind": "struct", "fields": [{"name": "varianceThreshold", "type": {"defined": "BorshDecimal"}}]}}, {"name": "CrankInitParams", "type": {"kind": "struct", "fields": [{"name": "name", "type": "bytes"}, {"name": "metadata", "type": "bytes"}, {"name": "crankSize", "type": "u32"}]}}, {"name": "CrankPopParams", "type": {"kind": "struct", "fields": [{"name": "stateBump", "type": "u8"}, {"name": "leaseBumps", "type": "bytes"}, {"name": "permissionBumps", "type": "bytes"}, {"name": "nonce", "type": {"option": "u32"}}, {"name": "failOpenOnAccountMismatch", "type": {"option": "bool"}}]}}, {"name": "CrankPushParams", "type": {"kind": "struct", "fields": [{"name": "stateBump", "type": "u8"}, {"name": "permissionBump", "type": "u8"}]}}, {"name": "EcvrfVerifyParams", "type": {"kind": "struct", "fields": [{"name": "proof", "type": "bytes"}, {"name": "alpha", "type": "bytes"}]}}, {"name": "JobInitParams", "type": {"kind": "struct", "fields": [{"name": "name", "type": {"array": ["u8", 32]}}, {"name": "expiration", "type": "i64"}, {"name": "stateBump", "type": "u8"}, {"name": "data", "type": "bytes"}]}}, {"name": "LeaseExtendParams", "type": {"kind": "struct", "fields": [{"name": "loadAmount", "type": "u64"}, {"name": "leaseBump", "type": "u8"}, {"name": "stateBump", "type": "u8"}]}}, {"name": "LeaseInitParams", "type": {"kind": "struct", "fields": [{"name": "loadAmount", "type": "u64"}, {"name": "withdrawAuthority", "type": "publicKey"}, {"name": "leaseBump", "type": "u8"}, {"name": "stateBump", "type": "u8"}]}}, {"name": "LeaseWithdrawParams", "type": {"kind": "struct", "fields": [{"name": "stateBump", "type": "u8"}, {"name": "leaseBump", "type": "u8"}, {"name": "amount", "type": "u64"}]}}, {"name": "OracleHeartbeatParams", "type": {"kind": "struct", "fields": [{"name": "permissionBump", "type": "u8"}]}}, {"name": "OracleInitParams", "type": {"kind": "struct", "fields": [{"name": "name", "type": "bytes"}, {"name": "metadata", "type": "bytes"}, {"name": "stateBump", "type": "u8"}, {"name": "oracleBump", "type": "u8"}]}}, {"name": "OracleQueueInitParams", "type": {"kind": "struct", "fields": [{"name": "name", "type": {"array": ["u8", 32]}}, {"name": "metadata", "type": {"array": ["u8", 64]}}, {"name": "reward", "type": "u64"}, {"name": "minStake", "type": "u64"}, {"name": "feedProbationPeriod", "type": "u32"}, {"name": "oracleTimeout", "type": "u32"}, {"name": "slashingEnabled", "type": "bool"}, {"name": "varianceToleranceMultiplier", "type": {"defined": "BorshDecimal"}}, {"name": "consecutiveFeedFailureLimit", "type": "u64"}, {"name": "consecutiveOracleFailureLimit", "type": "u64"}, {"name": "queueSize", "type": "u32"}, {"name": "unpermissionedFeeds", "type": "bool"}]}}, {"name": "OracleQueueSetRewardsParams", "type": {"kind": "struct", "fields": [{"name": "rewards", "type": "u64"}]}}, {"name": "OracleWithdrawParams", "type": {"kind": "struct", "fields": [{"name": "stateBump", "type": "u8"}, {"name": "permissionBump", "type": "u8"}, {"name": "amount", "type": "u64"}]}}, {"name": "PermissionInitParams", "type": {"kind": "struct", "fields": [{"name": "permissionBump", "type": "u8"}]}}, {"name": "PermissionSetParams", "type": {"kind": "struct", "fields": [{"name": "permission", "type": {"defined": "SwitchboardPermission"}}, {"name": "enable", "type": "bool"}]}}, {"name": "ProgramConfigParams", "type": {"kind": "struct", "fields": [{"name": "token", "type": "publicKey"}, {"name": "bump", "type": "u8"}]}}, {"name": "ProgramInitParams", "type": {"kind": "struct", "fields": [{"name": "stateBump", "type": "u8"}]}}, {"name": "Hash", "type": {"kind": "struct", "fields": [{"name": "data", "type": {"array": ["u8", 32]}}]}}, {"name": "AggregatorRound", "type": {"kind": "struct", "fields": [{"name": "numSuccess", "type": "u32"}, {"name": "numError", "type": "u32"}, {"name": "isClosed", "type": "bool"}, {"name": "roundOpenSlot", "type": "u64"}, {"name": "roundOpenTimestamp", "type": "i64"}, {"name": "result", "type": {"defined": "SwitchboardDecimal"}}, {"name": "stdDeviation", "type": {"defined": "SwitchboardDecimal"}}, {"name": "minResponse", "type": {"defined": "SwitchboardDecimal"}}, {"name": "maxResponse", "type": {"defined": "SwitchboardDecimal"}}, {"name": "oraclePubkeysData", "type": {"array": ["publicKey", 16]}}, {"name": "mediansData", "type": {"array": [{"defined": "SwitchboardDecimal"}, 16]}}, {"name": "currentPayout", "type": {"array": ["i64", 16]}}, {"name": "mediansFulfilled", "type": {"array": ["bool", 16]}}, {"name": "errorsFulfilled", "type": {"array": ["bool", 16]}}]}}, {"name": "AggregatorHistoryRow", "type": {"kind": "struct", "fields": [{"name": "timestamp", "type": "i64"}, {"name": "value", "type": {"defined": "SwitchboardDecimal"}}]}}, {"name": "SwitchboardDecimal", "type": {"kind": "struct", "fields": [{"name": "mantissa", "type": "i128"}, {"name": "scale", "type": "u32"}]}}, {"name": "VrfRound", "type": {"kind": "struct", "fields": [{"name": "vrfProducer", "type": "publicKey"}, {"name": "reprProof", "type": {"array": ["u8", 224]}}, {"name": "proof", "type": {"array": ["u8", 80]}}, {"name": "alpha", "type": {"array": ["u8", 64]}}, {"name": "alphaLen", "type": "u32"}, {"name": "stage", "type": "u32"}, {"name": "ebuf", "type": {"array": ["u8", 255]}}]}}, {"name": "CrankRow", "type": {"kind": "struct", "fields": [{"name": "pubkey", "type": "publicKey"}, {"name": "nextTimestamp", "type": "i64"}]}}, {"name": "OracleMetrics", "type": {"kind": "struct", "fields": [{"name": "consecutiveSuccess", "type": "u64"}, {"name": "consecutiveError", "type": "u64"}, {"name": "consecutiveDisagreement", "type": "u64"}, {"name": "consecutiveLateResponse", "type": "u64"}, {"name": "consecutiveFailure", "type": "u64"}, {"name": "totalSuccess", "type": "u128"}, {"name": "totalError", "type": "u128"}, {"name": "totalDisagreement", "type": "u128"}, {"name": "totalLateResponse", "type": "u128"}]}}, {"name": "BorshDecimal", "type": {"kind": "struct", "fields": [{"name": "mantissa", "type": "i128"}, {"name": "scale", "type": "u32"}]}}, {"name": "VaultTransferParams", "type": {"kind": "struct", "fields": [{"name": "stateBump", "type": "u8"}, {"name": "amount", "type": "u64"}]}}, {"name": "SwitchboardPermission", "type": {"kind": "enum", "variants": [{"name": "PermitOracleHeartbeat"}, {"name": "PermitOracleQueueUsage"}]}}, {"name": "OracleResponseType", "type": {"kind": "enum", "variants": [{"name": "TypeSuccess"}, {"name": "TypeError"}, {"name": "TypeDisagreement"}, {"name": "TypeNoResponse"}]}}, {"name": "Error", "type": {"kind": "enum", "variants": [{"name": "InvalidPublicKey"}, {"name": "SerializationError", "fields": [{"defined": "bincode::Error"}]}, {"name": "DeserializationError", "fields": [{"defined": "bincode::Error"}]}, {"name": "InvalidDataError"}]}}], "events": [{"name": "AggregatorInitEvent", "fields": [{"name": "feedPubkey", "type": "publicKey", "index": false}]}, {"name": "AggregatorOpenRoundEvent", "fields": [{"name": "feedPubkey", "type": "publicKey", "index": false}, {"name": "oraclePubkeys", "type": {"vec": "publicKey"}, "index": false}, {"name": "jobPubkeys", "type": {"vec": "publicKey"}, "index": false}, {"name": "remainingFunds", "type": "u64", "index": false}, {"name": "queueAuthority", "type": "publicKey", "index": false}]}, {"name": "AggregatorValueUpdateEvent", "fields": [{"name": "feedPubkey", "type": "publicKey", "index": false}, {"name": "value", "type": {"defined": "BorshDecimal"}, "index": false}, {"name": "slot", "type": "u64", "index": false}, {"name": "timestamp", "type": "i64", "index": false}, {"name": "oraclePubkeys", "type": {"vec": "publicKey"}, "index": false}, {"name": "oracleValues", "type": {"vec": {"defined": "BorshDecimal"}}, "index": false}]}, {"name": "OracleRewardEvent", "fields": [{"name": "feedPubkey", "type": "publicKey", "index": false}, {"name": "leasePubkey", "type": "publicKey", "index": false}, {"name": "oraclePubkey", "type": "publicKey", "index": false}, {"name": "walletPubkey", "type": "publicKey", "index": false}, {"name": "amount", "type": "u64", "index": false}, {"name": "roundSlot", "type": "u64", "index": false}, {"name": "timestamp", "type": "i64", "index": false}]}, {"name": "OracleWithdrawEvent", "fields": [{"name": "oraclePubkey", "type": "publicKey", "index": false}, {"name": "walletPubkey", "type": "publicKey", "index": false}, {"name": "destinationWallet", "type": "publicKey", "index": false}, {"name": "previousAmount", "type": "u64", "index": false}, {"name": "newAmount", "type": "u64", "index": false}, {"name": "timestamp", "type": "i64", "index": false}]}, {"name": "LeaseWithdrawEvent", "fields": [{"name": "leasePubkey", "type": "publicKey", "index": false}, {"name": "walletPubkey", "type": "publicKey", "index": false}, {"name": "previousAmount", "type": "u64", "index": false}, {"name": "newAmount", "type": "u64", "index": false}, {"name": "timestamp", "type": "i64", "index": false}]}, {"name": "OracleSlashEvent", "fields": [{"name": "feedPubkey", "type": "publicKey", "index": false}, {"name": "leasePubkey", "type": "publicKey", "index": false}, {"name": "oraclePubkey", "type": "publicKey", "index": false}, {"name": "walletPubkey", "type": "publicKey", "index": false}, {"name": "amount", "type": "u64", "index": false}, {"name": "roundSlot", "type": "u64", "index": false}, {"name": "timestamp", "type": "i64", "index": false}]}, {"name": "LeaseFundEvent", "fields": [{"name": "leasePubkey", "type": "publicKey", "index": false}, {"name": "funder", "type": "publicKey", "index": false}, {"name": "amount", "type": "u64", "index": false}, {"name": "timestamp", "type": "i64", "index": false}]}, {"name": "ProbationBrokenEvent", "fields": [{"name": "feedPubkey", "type": "publicKey", "index": false}, {"name": "queuePubkey", "type": "publicKey", "index": false}, {"name": "timestamp", "type": "i64", "index": false}]}, {"name": "FeedPermissionRevokedEvent", "fields": [{"name": "feedPubkey", "type": "publicKey", "index": false}, {"name": "timestamp", "type": "i64", "index": false}]}, {"name": "GarbageCollectFailureEvent", "fields": [{"name": "queuePubkey", "type": "publicKey", "index": false}]}, {"name": "OracleBootedEvent", "fields": [{"name": "queuePubkey", "type": "publicKey", "index": false}, {"name": "oraclePubkey", "type": "publicKey", "index": false}]}, {"name": "CrankLeaseInsufficientFundsEvent", "fields": [{"name": "feedPubkey", "type": "publicKey", "index": false}, {"name": "leasePubkey", "type": "publicKey", "index": false}]}, {"name": "CrankPopExpectedFailureEvent", "fields": [{"name": "feedPubkey", "type": "publicKey", "index": false}, {"name": "leasePubkey", "type": "publicKey", "index": false}]}], "errors": [{"code": 6000, "name": "ArrayOperationError", "msg": "Illegal operation on a Switchboard array."}, {"code": 6001, "name": "QueueOperationError", "msg": "Illegal operation on a Switchboard queue."}, {"code": 6002, "name": "IncorrectProgramOwnerError", "msg": "An account required to be owned by the program has a different owner."}, {"code": 6003, "name": "InvalidAggregatorRound", "msg": "Aggregator is not currently populated with a valid round."}, {"code": 6004, "name": "TooManyAggregatorJobs", "msg": "Aggregator cannot fit any more jobs."}, {"code": 6005, "name": "AggregatorCurrentRoundClosed", "msg": "Aggregator's current round is closed. No results are being accepted."}, {"code": 6006, "name": "AggregatorInvalidSaveResult", "msg": "Aggregator received an invalid save result instruction."}, {"code": 6007, "name": "InvalidStrDecimalConversion", "msg": "Failed to convert string to decimal format."}, {"code": 6008, "name": "AccountLoaderMissingSignature", "msg": "AccountLoader account is missing a required signature."}, {"code": 6009, "name": "MissingRequiredSignature", "msg": "Account is missing a required signature."}, {"code": 6010, "name": "ArrayOverflowError", "msg": "The attempted action will overflow a zero-copy account array."}, {"code": 6011, "name": "ArrayUnderflowError", "msg": "The attempted action will underflow a zero-copy account array."}, {"code": 6012, "name": "PubkeyNotFoundError", "msg": "The queried public key was not found."}, {"code": 6013, "name": "AggregatorIllegalRoundOpenCall", "msg": "Aggregator round open called too early."}, {"code": 6014, "name": "AggregatorIllegalRoundCloseCall", "msg": "Aggregator round close called too early."}, {"code": 6015, "name": "AggregatorClosedError", "msg": "Aggregator is closed. Illegal aciton."}, {"code": 6016, "name": "IllegalOracleIdxError", "msg": "Illegal oracle index."}, {"code": 6017, "name": "OracleAlreadyRespondedError", "msg": "The provided oracle has already responded this round."}, {"code": 6018, "name": "ProtoDeserializeError", "msg": "Failed to deserialize protocol buffer."}, {"code": 6019, "name": "UnauthorizedStateUpdateError", "msg": "Unathorized program state modification attempted."}, {"code": 6020, "name": "MissingOracleAccountsError", "msg": "Not enough oracle accounts provided to closeRounds."}, {"code": 6021, "name": "OracleMismatchError", "msg": "An unexpected oracle account was provided for the transaction."}, {"code": 6022, "name": "CrankMaxCapacityError", "msg": "Attempted to push to a Crank that's at capacity"}, {"code": 6023, "name": "AggregatorLeaseInsufficientFunds", "msg": "Aggregator update call attempted but attached lease has insufficient funds."}, {"code": 6024, "name": "IncorrectTokenAccountMint", "msg": "The provided token account does not point to the Switchbaord token mint."}, {"code": 6025, "name": "InvalidEscrowAccount", "msg": "An invalid escrow account was provided."}, {"code": 6026, "name": "CrankEmptyError", "msg": "Crank empty. Pop failed."}, {"code": 6027, "name": "PdaDeriveError", "msg": "Failed to derive a PDA from the provided seed."}, {"code": 6028, "name": "AggregatorAccountNotFound", "msg": "Aggregator account missing from provided account list."}, {"code": 6029, "name": "PermissionAccountNotFound", "msg": "Permission account missing from provided account list."}, {"code": 6030, "name": "LeaseAccountDeriveFailure", "msg": "Failed to derive a lease account."}, {"code": 6031, "name": "PermissionAccountDeriveFailure", "msg": "Failed to derive a permission account."}, {"code": 6032, "name": "EscrowAccountNotFound", "msg": "Escrow account missing from provided account list."}, {"code": 6033, "name": "LeaseAccountNotFound", "msg": "Lease account missing from provided account list."}, {"code": 6034, "name": "DecimalConversionError", "msg": "Decimal conversion method failed."}, {"code": 6035, "name": "PermissionDenied", "msg": "Permission account is missing required flags for the given action."}, {"code": 6036, "name": "QueueAtCapacity", "msg": "Oracle queue is at lease capacity."}, {"code": 6037, "name": "ExcessiveCrankRowsError", "msg": "Data feed is already pushed on a crank."}, {"code": 6038, "name": "AggregatorLockedError", "msg": "Aggregator is locked, no setting modifications or job additions allowed."}, {"code": 6039, "name": "AggregatorInvalidBatchSizeError", "msg": "Aggregator invalid batch size."}, {"code": 6040, "name": "AggregatorJobChecksumMismatch", "msg": "Oracle provided an incorrect aggregator job checksum."}, {"code": 6041, "name": "IntegerOverflowError", "msg": "An integer overflow occurred."}, {"code": 6042, "name": "InvalidUpdatePeriodError", "msg": "Mimimum update period is 5 seconds."}, {"code": 6043, "name": "NoResultsError", "msg": "Aggregator round evaluation attempted with no results."}, {"code": 6044, "name": "InvalidExpirationError", "msg": "An expiration constraint was broken."}, {"code": 6045, "name": "InsufficientStakeError", "msg": "An account provided insufficient stake for aciton."}, {"code": 6046, "name": "LeaseInactiveError", "msg": "The provided lease account is not active."}, {"code": 6047, "name": "NoAggregatorJobsFound", "msg": "No jobs are currently included in the aggregator."}, {"code": 6048, "name": "IntegerUnderflowError", "msg": "An integer underflow occurred."}, {"code": 6049, "name": "OracleQueueMismatch", "msg": "An invalid oracle queue account was provided."}, {"code": 6050, "name": "OracleWalletMismatchError", "msg": "An unexpected oracle wallet account was provided for the transaction."}, {"code": 6051, "name": "InvalidBufferAccountError", "msg": "An invalid buffer account was provided."}, {"code": 6052, "name": "InsufficientOracleQueueError", "msg": "Insufficient oracle queue size."}, {"code": 6053, "name": "InvalidAuthorityError", "msg": "Invalid authority account provided."}, {"code": 6054, "name": "InvalidTokenAccountMintError", "msg": "A provided token wallet is associated with an incorrect mint."}, {"code": 6055, "name": "ExcessiveLeaseWithdrawlError", "msg": "You must leave enough funds to perform at least 1 update in the lease."}, {"code": 6056, "name": "InvalideHistoryAccountError", "msg": "Invalid history account provided."}, {"code": 6057, "name": "InvalidLeaseAccountEscrowError", "msg": "Invalid lease account escrow."}, {"code": 6058, "name": "InvalidCrankAccountError", "msg": "Invalid crank provided."}, {"code": 6059, "name": "CrankNoElementsReadyError", "msg": "No elements ready to be popped."}, {"code": 6060, "name": "VrfVerifyError", "msg": "Error in verifying vrf proof."}]}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/switchboard_v2.mainnet.06022022.json b/basics/anchorpy-main/tests/idls/switchboard_v2.mainnet.06022022.json
new file mode 100644
index 0000000..1635cf8
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/switchboard_v2.mainnet.06022022.json
@@ -0,0 +1,4601 @@
+{
+ "version": "0.1.0",
+ "name": "switchboard_v2",
+ "instructions": [
+ {
+ "name": "aggregatorAddJob",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "job",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorAddJobParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorInit",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "queue",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "authorWallet",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorInitParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorLock",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": true,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorLockParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorOpenRound",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "lease",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "queueAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "permission",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payoutWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "dataBuffer",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorOpenRoundParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorRemoveJob",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "job",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorRemoveJobParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorSaveResult",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracle",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "oracleQueue",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "queueAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "feedPermission",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oraclePermission",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "lease",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "historyBuffer",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorSaveResultParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorSetAuthority",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "newAuthority",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorSetAuthorityParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorSetBatchSize",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorSetBatchSizeParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorSetHistoryBuffer",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "buffer",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorSetHistoryBufferParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorSetMinJobs",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorSetMinJobsParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorSetMinOracles",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorSetMinOraclesParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorSetQueue",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "queue",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorSetQueueParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorSetUpdateInterval",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorSetUpdateIntervalParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "aggregatorSetVarianceThreshold",
+ "accounts": [
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "AggregatorSetVarianceThresholdParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "crankInit",
+ "accounts": [
+ {
+ "name": "crank",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "queue",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "buffer",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "CrankInitParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "crankPop",
+ "accounts": [
+ {
+ "name": "crank",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "queueAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payoutWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "crankDataBuffer",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "queueDataBuffer",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "CrankPopParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "crankPush",
+ "accounts": [
+ {
+ "name": "crank",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "aggregator",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "queueAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "permission",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "lease",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "dataBuffer",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "CrankPushParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "jobInit",
+ "accounts": [
+ {
+ "name": "job",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authorWallet",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "JobInitParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "leaseExtend",
+ "accounts": [
+ {
+ "name": "lease",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "aggregator",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "queue",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "funder",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "LeaseExtendParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "leaseInit",
+ "accounts": [
+ {
+ "name": "lease",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "queue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "aggregator",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "funder",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "owner",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "LeaseInitParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "leaseSetAuthority",
+ "accounts": [
+ {
+ "name": "lease",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "newAuthority",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "LeaseSetAuthorityParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "leaseWithdraw",
+ "accounts": [
+ {
+ "name": "lease",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "aggregator",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "queue",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "withdrawAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "withdrawAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "LeaseWithdrawParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "oracleHeartbeat",
+ "accounts": [
+ {
+ "name": "oracle",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "tokenAccount",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "gcOracle",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "permission",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "dataBuffer",
+ "isMut": true,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "OracleHeartbeatParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "oracleInit",
+ "accounts": [
+ {
+ "name": "oracle",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "wallet",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "queue",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "OracleInitParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "oracleQueueInit",
+ "accounts": [
+ {
+ "name": "oracleQueue",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "buffer",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "OracleQueueInitParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "oracleQueueSetRewards",
+ "accounts": [
+ {
+ "name": "queue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "OracleQueueSetRewardsParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "oracleQueueVrfConfig",
+ "accounts": [
+ {
+ "name": "queue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "OracleQueueVrfConfigParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "oracleWithdraw",
+ "accounts": [
+ {
+ "name": "oracle",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "tokenAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "withdrawAccount",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "permission",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "OracleWithdrawParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "permissionInit",
+ "accounts": [
+ {
+ "name": "permission",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "granter",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "grantee",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "PermissionInitParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "permissionSet",
+ "accounts": [
+ {
+ "name": "permission",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "PermissionSetParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "programConfig",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "ProgramConfigParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "programInit",
+ "accounts": [
+ {
+ "name": "state",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenMint",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payer",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "ProgramInitParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "vaultTransfer",
+ "accounts": [
+ {
+ "name": "state",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "to",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "vault",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "VaultTransferParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "vrfInit",
+ "accounts": [
+ {
+ "name": "vrf",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "oracleQueue",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "VrfInitParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "vrfProve",
+ "accounts": [
+ {
+ "name": "vrf",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracle",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "randomnessProducer",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "VrfProveParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "vrfProveAndVerify",
+ "accounts": [
+ {
+ "name": "vrf",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "callbackPid",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "oracle",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "oracleAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "oracleWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "instructionsSysvar",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "VrfProveAndVerifyParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "vrfRequestRandomness",
+ "accounts": [
+ {
+ "name": "authority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "vrf",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "oracleQueue",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "queueAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "dataBuffer",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "permission",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payerWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "payerAuthority",
+ "isMut": false,
+ "isSigner": true
+ },
+ {
+ "name": "recentBlockhashes",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "VrfRequestRandomnessParams"
+ }
+ }
+ ]
+ },
+ {
+ "name": "vrfVerify",
+ "accounts": [
+ {
+ "name": "vrf",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "callbackPid",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "tokenProgram",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "escrow",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "programState",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "oracle",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "oracleAuthority",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "oracleWallet",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "instructionsSysvar",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "params",
+ "type": {
+ "defined": "VrfVerifyParams"
+ }
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "SbState",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "tokenMint",
+ "type": "publicKey"
+ },
+ {
+ "name": "tokenVault",
+ "type": "publicKey"
+ },
+ {
+ "name": "ebuf",
+ "type": {
+ "array": ["u8", 1024]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorAccountData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "metadata",
+ "type": {
+ "array": ["u8", 128]
+ }
+ },
+ {
+ "name": "authorWallet",
+ "type": "publicKey"
+ },
+ {
+ "name": "queuePubkey",
+ "type": "publicKey"
+ },
+ {
+ "name": "oracleRequestBatchSize",
+ "type": "u32"
+ },
+ {
+ "name": "minOracleResults",
+ "type": "u32"
+ },
+ {
+ "name": "minJobResults",
+ "type": "u32"
+ },
+ {
+ "name": "minUpdateDelaySeconds",
+ "type": "u32"
+ },
+ {
+ "name": "startAfter",
+ "type": "i64"
+ },
+ {
+ "name": "varianceThreshold",
+ "type": {
+ "defined": "SwitchboardDecimal"
+ }
+ },
+ {
+ "name": "forceReportPeriod",
+ "type": "i64"
+ },
+ {
+ "name": "expiration",
+ "type": "i64"
+ },
+ {
+ "name": "consecutiveFailureCount",
+ "type": "u64"
+ },
+ {
+ "name": "nextAllowedUpdateTime",
+ "type": "i64"
+ },
+ {
+ "name": "isLocked",
+ "type": "bool"
+ },
+ {
+ "name": "crankPubkey",
+ "type": "publicKey"
+ },
+ {
+ "name": "latestConfirmedRound",
+ "type": {
+ "defined": "AggregatorRound"
+ }
+ },
+ {
+ "name": "currentRound",
+ "type": {
+ "defined": "AggregatorRound"
+ }
+ },
+ {
+ "name": "jobPubkeysData",
+ "type": {
+ "array": ["publicKey", 16]
+ }
+ },
+ {
+ "name": "jobHashes",
+ "type": {
+ "array": [
+ {
+ "defined": "Hash"
+ },
+ 16
+ ]
+ }
+ },
+ {
+ "name": "jobPubkeysSize",
+ "type": "u32"
+ },
+ {
+ "name": "jobsChecksum",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "historyBuffer",
+ "type": "publicKey"
+ },
+ {
+ "name": "previousConfirmedRoundResult",
+ "type": {
+ "defined": "SwitchboardDecimal"
+ }
+ },
+ {
+ "name": "previousConfirmedRoundSlot",
+ "type": "u64"
+ },
+ {
+ "name": "disableCrank",
+ "type": "bool"
+ },
+ {
+ "name": "ebuf",
+ "type": {
+ "array": ["u8", 163]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "PermissionAccountData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "permissions",
+ "type": "u32"
+ },
+ {
+ "name": "granter",
+ "type": "publicKey"
+ },
+ {
+ "name": "grantee",
+ "type": "publicKey"
+ },
+ {
+ "name": "expiration",
+ "type": "i64"
+ },
+ {
+ "name": "ebuf",
+ "type": {
+ "array": ["u8", 256]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "LeaseAccountData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "escrow",
+ "type": "publicKey"
+ },
+ {
+ "name": "queue",
+ "type": "publicKey"
+ },
+ {
+ "name": "aggregator",
+ "type": "publicKey"
+ },
+ {
+ "name": "tokenProgram",
+ "type": "publicKey"
+ },
+ {
+ "name": "isActive",
+ "type": "bool"
+ },
+ {
+ "name": "crankRowCount",
+ "type": "u32"
+ },
+ {
+ "name": "createdAt",
+ "type": "i64"
+ },
+ {
+ "name": "updateCount",
+ "type": "u128"
+ },
+ {
+ "name": "withdrawAuthority",
+ "type": "publicKey"
+ },
+ {
+ "name": "ebuf",
+ "type": {
+ "array": ["u8", 256]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleQueueAccountData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "metadata",
+ "type": {
+ "array": ["u8", 64]
+ }
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "oracleTimeout",
+ "type": "u32"
+ },
+ {
+ "name": "reward",
+ "type": "u64"
+ },
+ {
+ "name": "minStake",
+ "type": "u64"
+ },
+ {
+ "name": "slashingEnabled",
+ "type": "bool"
+ },
+ {
+ "name": "varianceToleranceMultiplier",
+ "type": {
+ "defined": "SwitchboardDecimal"
+ }
+ },
+ {
+ "name": "feedProbationPeriod",
+ "type": "u32"
+ },
+ {
+ "name": "currIdx",
+ "type": "u32"
+ },
+ {
+ "name": "size",
+ "type": "u32"
+ },
+ {
+ "name": "gcIdx",
+ "type": "u32"
+ },
+ {
+ "name": "consecutiveFeedFailureLimit",
+ "type": "u64"
+ },
+ {
+ "name": "consecutiveOracleFailureLimit",
+ "type": "u64"
+ },
+ {
+ "name": "unpermissionedFeedsEnabled",
+ "type": "bool"
+ },
+ {
+ "name": "unpermissionedVrfEnabled",
+ "type": "bool"
+ },
+ {
+ "name": "curatorRewardCut",
+ "type": {
+ "defined": "SwitchboardDecimal"
+ }
+ },
+ {
+ "name": "lockLeaseFunding",
+ "type": "bool"
+ },
+ {
+ "name": "ebuf",
+ "type": {
+ "array": ["u8", 1001]
+ }
+ },
+ {
+ "name": "maxSize",
+ "type": "u32"
+ },
+ {
+ "name": "dataBuffer",
+ "type": "publicKey"
+ }
+ ]
+ }
+ },
+ {
+ "name": "CrankAccountData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "metadata",
+ "type": {
+ "array": ["u8", 64]
+ }
+ },
+ {
+ "name": "queuePubkey",
+ "type": "publicKey"
+ },
+ {
+ "name": "pqSize",
+ "type": "u32"
+ },
+ {
+ "name": "maxRows",
+ "type": "u32"
+ },
+ {
+ "name": "jitterModifier",
+ "type": "u8"
+ },
+ {
+ "name": "ebuf",
+ "type": {
+ "array": ["u8", 255]
+ }
+ },
+ {
+ "name": "dataBuffer",
+ "type": "publicKey"
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleAccountData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "metadata",
+ "type": {
+ "array": ["u8", 128]
+ }
+ },
+ {
+ "name": "oracleAuthority",
+ "type": "publicKey"
+ },
+ {
+ "name": "lastHeartbeat",
+ "type": "i64"
+ },
+ {
+ "name": "numInUse",
+ "type": "u32"
+ },
+ {
+ "name": "tokenAccount",
+ "type": "publicKey"
+ },
+ {
+ "name": "queuePubkey",
+ "type": "publicKey"
+ },
+ {
+ "name": "metrics",
+ "type": {
+ "defined": "OracleMetrics"
+ }
+ },
+ {
+ "name": "ebuf",
+ "type": {
+ "array": ["u8", 256]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "JobAccountData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "metadata",
+ "type": {
+ "array": ["u8", 64]
+ }
+ },
+ {
+ "name": "authorWallet",
+ "type": "publicKey"
+ },
+ {
+ "name": "expiration",
+ "type": "i64"
+ },
+ {
+ "name": "hash",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "data",
+ "type": "bytes"
+ },
+ {
+ "name": "referenceCount",
+ "type": "u32"
+ },
+ {
+ "name": "totalSpent",
+ "type": "u128"
+ }
+ ]
+ }
+ },
+ {
+ "name": "VrfAccountData",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "status",
+ "type": {
+ "defined": "VrfStatus"
+ }
+ },
+ {
+ "name": "counter",
+ "type": "u128"
+ },
+ {
+ "name": "authority",
+ "type": "publicKey"
+ },
+ {
+ "name": "oracleQueue",
+ "type": "publicKey"
+ },
+ {
+ "name": "escrow",
+ "type": "publicKey"
+ },
+ {
+ "name": "callback",
+ "type": {
+ "defined": "CallbackZC"
+ }
+ },
+ {
+ "name": "batchSize",
+ "type": "u32"
+ },
+ {
+ "name": "builders",
+ "type": {
+ "array": [
+ {
+ "defined": "VrfBuilder"
+ },
+ 8
+ ]
+ }
+ },
+ {
+ "name": "buildersLen",
+ "type": "u32"
+ },
+ {
+ "name": "testMode",
+ "type": "bool"
+ },
+ {
+ "name": "currentRound",
+ "type": {
+ "defined": "VrfRound"
+ }
+ },
+ {
+ "name": "ebuf",
+ "type": {
+ "array": ["u8", 1024]
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "AggregatorAddJobParams",
+ "type": {
+ "kind": "struct",
+ "fields": []
+ }
+ },
+ {
+ "name": "AggregatorInitParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "metadata",
+ "type": {
+ "array": ["u8", 128]
+ }
+ },
+ {
+ "name": "batchSize",
+ "type": "u32"
+ },
+ {
+ "name": "minOracleResults",
+ "type": "u32"
+ },
+ {
+ "name": "minJobResults",
+ "type": "u32"
+ },
+ {
+ "name": "minUpdateDelaySeconds",
+ "type": "u32"
+ },
+ {
+ "name": "startAfter",
+ "type": "i64"
+ },
+ {
+ "name": "varianceThreshold",
+ "type": {
+ "defined": "BorshDecimal"
+ }
+ },
+ {
+ "name": "forceReportPeriod",
+ "type": "i64"
+ },
+ {
+ "name": "expiration",
+ "type": "i64"
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorLockParams",
+ "type": {
+ "kind": "struct",
+ "fields": []
+ }
+ },
+ {
+ "name": "AggregatorOpenRoundParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "leaseBump",
+ "type": "u8"
+ },
+ {
+ "name": "permissionBump",
+ "type": "u8"
+ },
+ {
+ "name": "jitter",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorRemoveJobParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "jobIdx",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorSaveResultParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "oracleIdx",
+ "type": "u32"
+ },
+ {
+ "name": "error",
+ "type": "bool"
+ },
+ {
+ "name": "value",
+ "type": {
+ "defined": "BorshDecimal"
+ }
+ },
+ {
+ "name": "jobsChecksum",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "minResponse",
+ "type": {
+ "defined": "BorshDecimal"
+ }
+ },
+ {
+ "name": "maxResponse",
+ "type": {
+ "defined": "BorshDecimal"
+ }
+ },
+ {
+ "name": "feedPermissionBump",
+ "type": "u8"
+ },
+ {
+ "name": "oraclePermissionBump",
+ "type": "u8"
+ },
+ {
+ "name": "leaseBump",
+ "type": "u8"
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorSetAuthorityParams",
+ "type": {
+ "kind": "struct",
+ "fields": []
+ }
+ },
+ {
+ "name": "AggregatorSetBatchSizeParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "batchSize",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorSetHistoryBufferParams",
+ "type": {
+ "kind": "struct",
+ "fields": []
+ }
+ },
+ {
+ "name": "AggregatorSetMinJobsParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "minJobResults",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorSetMinOraclesParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "minOracleResults",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorSetQueueParams",
+ "type": {
+ "kind": "struct",
+ "fields": []
+ }
+ },
+ {
+ "name": "AggregatorSetUpdateIntervalParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "newInterval",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorSetVarianceThresholdParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "varianceThreshold",
+ "type": {
+ "defined": "BorshDecimal"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "CrankInitParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": "bytes"
+ },
+ {
+ "name": "metadata",
+ "type": "bytes"
+ },
+ {
+ "name": "crankSize",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "CrankPopParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "leaseBumps",
+ "type": "bytes"
+ },
+ {
+ "name": "permissionBumps",
+ "type": "bytes"
+ },
+ {
+ "name": "nonce",
+ "type": {
+ "option": "u32"
+ }
+ },
+ {
+ "name": "failOpenOnAccountMismatch",
+ "type": {
+ "option": "bool"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "CrankPushParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "permissionBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "JobInitParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "expiration",
+ "type": "i64"
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "data",
+ "type": "bytes"
+ }
+ ]
+ }
+ },
+ {
+ "name": "LeaseExtendParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "loadAmount",
+ "type": "u64"
+ },
+ {
+ "name": "leaseBump",
+ "type": "u8"
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "LeaseInitParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "loadAmount",
+ "type": "u64"
+ },
+ {
+ "name": "withdrawAuthority",
+ "type": "publicKey"
+ },
+ {
+ "name": "leaseBump",
+ "type": "u8"
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "LeaseSetAuthorityParams",
+ "type": {
+ "kind": "struct",
+ "fields": []
+ }
+ },
+ {
+ "name": "LeaseWithdrawParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "leaseBump",
+ "type": "u8"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleHeartbeatParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "permissionBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleInitParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": "bytes"
+ },
+ {
+ "name": "metadata",
+ "type": "bytes"
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "oracleBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleQueueInitParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "name",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "metadata",
+ "type": {
+ "array": ["u8", 64]
+ }
+ },
+ {
+ "name": "reward",
+ "type": "u64"
+ },
+ {
+ "name": "minStake",
+ "type": "u64"
+ },
+ {
+ "name": "feedProbationPeriod",
+ "type": "u32"
+ },
+ {
+ "name": "oracleTimeout",
+ "type": "u32"
+ },
+ {
+ "name": "slashingEnabled",
+ "type": "bool"
+ },
+ {
+ "name": "varianceToleranceMultiplier",
+ "type": {
+ "defined": "BorshDecimal"
+ }
+ },
+ {
+ "name": "consecutiveFeedFailureLimit",
+ "type": "u64"
+ },
+ {
+ "name": "consecutiveOracleFailureLimit",
+ "type": "u64"
+ },
+ {
+ "name": "queueSize",
+ "type": "u32"
+ },
+ {
+ "name": "unpermissionedFeeds",
+ "type": "bool"
+ },
+ {
+ "name": "unpermissionedVrf",
+ "type": "bool"
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleQueueSetRewardsParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "rewards",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleQueueVrfConfigParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "unpermissionedVrfEnabled",
+ "type": "bool"
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleWithdrawParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "permissionBump",
+ "type": "u8"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "PermissionInitParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "permissionBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "PermissionSetParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "permission",
+ "type": {
+ "defined": "SwitchboardPermission"
+ }
+ },
+ {
+ "name": "enable",
+ "type": "bool"
+ }
+ ]
+ }
+ },
+ {
+ "name": "ProgramConfigParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "token",
+ "type": "publicKey"
+ },
+ {
+ "name": "bump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "ProgramInitParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "stateBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "VaultTransferParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "amount",
+ "type": "u64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "VrfInitParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "callback",
+ "type": {
+ "defined": "Callback"
+ }
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "VrfProveParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "proof",
+ "type": "bytes"
+ },
+ {
+ "name": "idx",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "VrfProveAndVerifyParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "nonce",
+ "type": {
+ "option": "u32"
+ }
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "idx",
+ "type": "u32"
+ },
+ {
+ "name": "proof",
+ "type": "bytes"
+ }
+ ]
+ }
+ },
+ {
+ "name": "VrfRequestRandomnessParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "permissionBump",
+ "type": "u8"
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "VrfVerifyParams",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "nonce",
+ "type": {
+ "option": "u32"
+ }
+ },
+ {
+ "name": "stateBump",
+ "type": "u8"
+ },
+ {
+ "name": "idx",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Hash",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "data",
+ "type": {
+ "array": ["u8", 32]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorRound",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "numSuccess",
+ "type": "u32"
+ },
+ {
+ "name": "numError",
+ "type": "u32"
+ },
+ {
+ "name": "isClosed",
+ "type": "bool"
+ },
+ {
+ "name": "roundOpenSlot",
+ "type": "u64"
+ },
+ {
+ "name": "roundOpenTimestamp",
+ "type": "i64"
+ },
+ {
+ "name": "result",
+ "type": {
+ "defined": "SwitchboardDecimal"
+ }
+ },
+ {
+ "name": "stdDeviation",
+ "type": {
+ "defined": "SwitchboardDecimal"
+ }
+ },
+ {
+ "name": "minResponse",
+ "type": {
+ "defined": "SwitchboardDecimal"
+ }
+ },
+ {
+ "name": "maxResponse",
+ "type": {
+ "defined": "SwitchboardDecimal"
+ }
+ },
+ {
+ "name": "oraclePubkeysData",
+ "type": {
+ "array": ["publicKey", 16]
+ }
+ },
+ {
+ "name": "mediansData",
+ "type": {
+ "array": [
+ {
+ "defined": "SwitchboardDecimal"
+ },
+ 16
+ ]
+ }
+ },
+ {
+ "name": "currentPayout",
+ "type": {
+ "array": ["i64", 16]
+ }
+ },
+ {
+ "name": "mediansFulfilled",
+ "type": {
+ "array": ["bool", 16]
+ }
+ },
+ {
+ "name": "errorsFulfilled",
+ "type": {
+ "array": ["bool", 16]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "AggregatorHistoryRow",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "timestamp",
+ "type": "i64"
+ },
+ {
+ "name": "value",
+ "type": {
+ "defined": "SwitchboardDecimal"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "SwitchboardDecimal",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "mantissa",
+ "type": "i128"
+ },
+ {
+ "name": "scale",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "CrankRow",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "pubkey",
+ "type": "publicKey"
+ },
+ {
+ "name": "nextTimestamp",
+ "type": "i64"
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleMetrics",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "consecutiveSuccess",
+ "type": "u64"
+ },
+ {
+ "name": "consecutiveError",
+ "type": "u64"
+ },
+ {
+ "name": "consecutiveDisagreement",
+ "type": "u64"
+ },
+ {
+ "name": "consecutiveLateResponse",
+ "type": "u64"
+ },
+ {
+ "name": "consecutiveFailure",
+ "type": "u64"
+ },
+ {
+ "name": "totalSuccess",
+ "type": "u128"
+ },
+ {
+ "name": "totalError",
+ "type": "u128"
+ },
+ {
+ "name": "totalDisagreement",
+ "type": "u128"
+ },
+ {
+ "name": "totalLateResponse",
+ "type": "u128"
+ }
+ ]
+ }
+ },
+ {
+ "name": "BorshDecimal",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "mantissa",
+ "type": "i128"
+ },
+ {
+ "name": "scale",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "EcvrfProofZC",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "gamma",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "c",
+ "type": {
+ "defined": "Scalar"
+ }
+ },
+ {
+ "name": "s",
+ "type": {
+ "defined": "Scalar"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Scalar",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "bytes",
+ "type": {
+ "array": ["u8", 32]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "FieldElementZC",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "bytes",
+ "type": {
+ "array": ["u64", 5]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "CompletedPointZC",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "x",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "y",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "z",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "t",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "EdwardsPointZC",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "x",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "y",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "z",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "t",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "ProjectivePointZC",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "x",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "y",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "z",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "EcvrfIntermediate",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "r",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "nS",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "d",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "t13",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "t15",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "VrfBuilder",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "producer",
+ "type": "publicKey"
+ },
+ {
+ "name": "status",
+ "type": {
+ "defined": "VrfStatus"
+ }
+ },
+ {
+ "name": "reprProof",
+ "type": {
+ "array": ["u8", 80]
+ }
+ },
+ {
+ "name": "proof",
+ "type": {
+ "defined": "EcvrfProofZC"
+ }
+ },
+ {
+ "name": "yPoint",
+ "type": "publicKey"
+ },
+ {
+ "name": "stage",
+ "type": "u32"
+ },
+ {
+ "name": "stage1Out",
+ "type": {
+ "defined": "EcvrfIntermediate"
+ }
+ },
+ {
+ "name": "r1",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "r2",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "stage3Out",
+ "type": {
+ "defined": "EcvrfIntermediate"
+ }
+ },
+ {
+ "name": "hPoint",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "sReduced",
+ "type": {
+ "defined": "Scalar"
+ }
+ },
+ {
+ "name": "yPointBuilder",
+ "type": {
+ "array": [
+ {
+ "defined": "FieldElementZC"
+ },
+ 3
+ ]
+ }
+ },
+ {
+ "name": "yRistrettoPoint",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "mulRound",
+ "type": "u8"
+ },
+ {
+ "name": "hashPointsRound",
+ "type": "u8"
+ },
+ {
+ "name": "mulTmp1",
+ "type": {
+ "defined": "CompletedPointZC"
+ }
+ },
+ {
+ "name": "uPoint1",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "uPoint2",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "vPoint1",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "vPoint2",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "uPoint",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "vPoint",
+ "type": {
+ "defined": "EdwardsPointZC"
+ }
+ },
+ {
+ "name": "u1",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "u2",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "invertee",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "y",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "z",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "p1Bytes",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "p2Bytes",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "p3Bytes",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "p4Bytes",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "cPrimeHashbuf",
+ "type": {
+ "array": ["u8", 16]
+ }
+ },
+ {
+ "name": "m1",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "m2",
+ "type": {
+ "defined": "FieldElementZC"
+ }
+ },
+ {
+ "name": "txRemaining",
+ "type": "u32"
+ },
+ {
+ "name": "verified",
+ "type": "bool"
+ },
+ {
+ "name": "result",
+ "type": {
+ "array": ["u8", 32]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "AccountMetaZC",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "pubkey",
+ "type": "publicKey"
+ },
+ {
+ "name": "isSigner",
+ "type": "bool"
+ },
+ {
+ "name": "isWritable",
+ "type": "bool"
+ }
+ ]
+ }
+ },
+ {
+ "name": "AccountMetaBorsh",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "pubkey",
+ "type": "publicKey"
+ },
+ {
+ "name": "isSigner",
+ "type": "bool"
+ },
+ {
+ "name": "isWritable",
+ "type": "bool"
+ }
+ ]
+ }
+ },
+ {
+ "name": "CallbackZC",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "programId",
+ "type": "publicKey"
+ },
+ {
+ "name": "accounts",
+ "type": {
+ "array": [
+ {
+ "defined": "AccountMetaZC"
+ },
+ 32
+ ]
+ }
+ },
+ {
+ "name": "accountsLen",
+ "type": "u32"
+ },
+ {
+ "name": "ixData",
+ "type": {
+ "array": ["u8", 1024]
+ }
+ },
+ {
+ "name": "ixDataLen",
+ "type": "u32"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Callback",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "programId",
+ "type": "publicKey"
+ },
+ {
+ "name": "accounts",
+ "type": {
+ "vec": {
+ "defined": "AccountMetaBorsh"
+ }
+ }
+ },
+ {
+ "name": "ixData",
+ "type": "bytes"
+ }
+ ]
+ }
+ },
+ {
+ "name": "VrfRound",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "alpha",
+ "type": {
+ "array": ["u8", 256]
+ }
+ },
+ {
+ "name": "alphaLen",
+ "type": "u32"
+ },
+ {
+ "name": "requestSlot",
+ "type": "u64"
+ },
+ {
+ "name": "requestTimestamp",
+ "type": "i64"
+ },
+ {
+ "name": "result",
+ "type": {
+ "array": ["u8", 32]
+ }
+ },
+ {
+ "name": "numVerified",
+ "type": "u32"
+ },
+ {
+ "name": "ebuf",
+ "type": {
+ "array": ["u8", 256]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "Lanes",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "C"
+ },
+ {
+ "name": "D"
+ },
+ {
+ "name": "AB"
+ },
+ {
+ "name": "AC"
+ },
+ {
+ "name": "CD"
+ },
+ {
+ "name": "AD"
+ },
+ {
+ "name": "BC"
+ },
+ {
+ "name": "ABCD"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Shuffle",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "AAAA"
+ },
+ {
+ "name": "BBBB"
+ },
+ {
+ "name": "CACA"
+ },
+ {
+ "name": "DBBD"
+ },
+ {
+ "name": "ADDA"
+ },
+ {
+ "name": "CBCB"
+ },
+ {
+ "name": "ABAB"
+ },
+ {
+ "name": "BADC"
+ },
+ {
+ "name": "BACD"
+ },
+ {
+ "name": "ABDC"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Shuffle",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "AAAA"
+ },
+ {
+ "name": "BBBB"
+ },
+ {
+ "name": "BADC"
+ },
+ {
+ "name": "BACD"
+ },
+ {
+ "name": "ADDA"
+ },
+ {
+ "name": "CBCB"
+ },
+ {
+ "name": "ABDC"
+ },
+ {
+ "name": "ABAB"
+ },
+ {
+ "name": "DBBD"
+ },
+ {
+ "name": "CACA"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Lanes",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "D"
+ },
+ {
+ "name": "C"
+ },
+ {
+ "name": "AB"
+ },
+ {
+ "name": "AC"
+ },
+ {
+ "name": "AD"
+ },
+ {
+ "name": "BCD"
+ }
+ ]
+ }
+ },
+ {
+ "name": "SwitchboardPermission",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "PermitOracleHeartbeat"
+ },
+ {
+ "name": "PermitOracleQueueUsage"
+ },
+ {
+ "name": "PermitVrfRequests"
+ }
+ ]
+ }
+ },
+ {
+ "name": "OracleResponseType",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "TypeSuccess"
+ },
+ {
+ "name": "TypeError"
+ },
+ {
+ "name": "TypeDisagreement"
+ },
+ {
+ "name": "TypeNoResponse"
+ }
+ ]
+ }
+ },
+ {
+ "name": "VrfStatus",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "StatusNone"
+ },
+ {
+ "name": "StatusRequesting"
+ },
+ {
+ "name": "StatusVerifying"
+ },
+ {
+ "name": "StatusVerified"
+ },
+ {
+ "name": "StatusCallbackSuccess"
+ },
+ {
+ "name": "StatusVerifyFailure"
+ }
+ ]
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "AggregatorInitEvent",
+ "fields": [
+ {
+ "name": "feedPubkey",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "VrfRequestRandomnessEvent",
+ "fields": [
+ {
+ "name": "vrfPubkey",
+ "type": "publicKey",
+ "index": true
+ },
+ {
+ "name": "oraclePubkeys",
+ "type": {
+ "vec": "publicKey"
+ },
+ "index": false
+ },
+ {
+ "name": "loadAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "existingAmount",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "VrfRequestEvent",
+ "fields": [
+ {
+ "name": "vrfPubkey",
+ "type": "publicKey",
+ "index": true
+ },
+ {
+ "name": "oraclePubkeys",
+ "type": {
+ "vec": "publicKey"
+ },
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "VrfProveEvent",
+ "fields": [
+ {
+ "name": "vrfPubkey",
+ "type": "publicKey",
+ "index": true
+ },
+ {
+ "name": "oraclePubkey",
+ "type": "publicKey",
+ "index": true
+ },
+ {
+ "name": "authorityPubkey",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "VrfVerifyEvent",
+ "fields": [
+ {
+ "name": "vrfPubkey",
+ "type": "publicKey",
+ "index": true
+ },
+ {
+ "name": "oraclePubkey",
+ "type": "publicKey",
+ "index": true
+ },
+ {
+ "name": "authorityPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "VrfCallbackPerformedEvent",
+ "fields": [
+ {
+ "name": "vrfPubkey",
+ "type": "publicKey",
+ "index": true
+ },
+ {
+ "name": "oraclePubkey",
+ "type": "publicKey",
+ "index": true
+ },
+ {
+ "name": "amount",
+ "type": "u64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AggregatorOpenRoundEvent",
+ "fields": [
+ {
+ "name": "feedPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "oraclePubkeys",
+ "type": {
+ "vec": "publicKey"
+ },
+ "index": false
+ },
+ {
+ "name": "jobPubkeys",
+ "type": {
+ "vec": "publicKey"
+ },
+ "index": false
+ },
+ {
+ "name": "remainingFunds",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "queueAuthority",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "AggregatorValueUpdateEvent",
+ "fields": [
+ {
+ "name": "feedPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "value",
+ "type": {
+ "defined": "BorshDecimal"
+ },
+ "index": false
+ },
+ {
+ "name": "slot",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ },
+ {
+ "name": "oraclePubkeys",
+ "type": {
+ "vec": "publicKey"
+ },
+ "index": false
+ },
+ {
+ "name": "oracleValues",
+ "type": {
+ "vec": {
+ "defined": "BorshDecimal"
+ }
+ },
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "OracleRewardEvent",
+ "fields": [
+ {
+ "name": "feedPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "leasePubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "oraclePubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "walletPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "roundSlot",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "OracleWithdrawEvent",
+ "fields": [
+ {
+ "name": "oraclePubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "walletPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "destinationWallet",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "previousAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "newAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "LeaseWithdrawEvent",
+ "fields": [
+ {
+ "name": "leasePubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "walletPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "previousAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "newAmount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "OracleSlashEvent",
+ "fields": [
+ {
+ "name": "feedPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "leasePubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "oraclePubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "walletPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "roundSlot",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "LeaseFundEvent",
+ "fields": [
+ {
+ "name": "leasePubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "funder",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "amount",
+ "type": "u64",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "ProbationBrokenEvent",
+ "fields": [
+ {
+ "name": "feedPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "queuePubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "FeedPermissionRevokedEvent",
+ "fields": [
+ {
+ "name": "feedPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "timestamp",
+ "type": "i64",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "GarbageCollectFailureEvent",
+ "fields": [
+ {
+ "name": "queuePubkey",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "OracleBootedEvent",
+ "fields": [
+ {
+ "name": "queuePubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "oraclePubkey",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "CrankLeaseInsufficientFundsEvent",
+ "fields": [
+ {
+ "name": "feedPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "leasePubkey",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ },
+ {
+ "name": "CrankPopExpectedFailureEvent",
+ "fields": [
+ {
+ "name": "feedPubkey",
+ "type": "publicKey",
+ "index": false
+ },
+ {
+ "name": "leasePubkey",
+ "type": "publicKey",
+ "index": false
+ }
+ ]
+ }
+ ],
+ "errors": [
+ {
+ "code": 6000,
+ "name": "ArrayOperationError",
+ "msg": "Illegal operation on a Switchboard array."
+ },
+ {
+ "code": 6001,
+ "name": "QueueOperationError",
+ "msg": "Illegal operation on a Switchboard queue."
+ },
+ {
+ "code": 6002,
+ "name": "IncorrectProgramOwnerError",
+ "msg": "An account required to be owned by the program has a different owner."
+ },
+ {
+ "code": 6003,
+ "name": "InvalidAggregatorRound",
+ "msg": "Aggregator is not currently populated with a valid round."
+ },
+ {
+ "code": 6004,
+ "name": "TooManyAggregatorJobs",
+ "msg": "Aggregator cannot fit any more jobs."
+ },
+ {
+ "code": 6005,
+ "name": "AggregatorCurrentRoundClosed",
+ "msg": "Aggregator's current round is closed. No results are being accepted."
+ },
+ {
+ "code": 6006,
+ "name": "AggregatorInvalidSaveResult",
+ "msg": "Aggregator received an invalid save result instruction."
+ },
+ {
+ "code": 6007,
+ "name": "InvalidStrDecimalConversion",
+ "msg": "Failed to convert string to decimal format."
+ },
+ {
+ "code": 6008,
+ "name": "AccountLoaderMissingSignature",
+ "msg": "AccountLoader account is missing a required signature."
+ },
+ {
+ "code": 6009,
+ "name": "MissingRequiredSignature",
+ "msg": "Account is missing a required signature."
+ },
+ {
+ "code": 6010,
+ "name": "ArrayOverflowError",
+ "msg": "The attempted action will overflow a zero-copy account array."
+ },
+ {
+ "code": 6011,
+ "name": "ArrayUnderflowError",
+ "msg": "The attempted action will underflow a zero-copy account array."
+ },
+ {
+ "code": 6012,
+ "name": "PubkeyNotFoundError",
+ "msg": "The queried public key was not found."
+ },
+ {
+ "code": 6013,
+ "name": "AggregatorIllegalRoundOpenCall",
+ "msg": "Aggregator round open called too early."
+ },
+ {
+ "code": 6014,
+ "name": "AggregatorIllegalRoundCloseCall",
+ "msg": "Aggregator round close called too early."
+ },
+ {
+ "code": 6015,
+ "name": "AggregatorClosedError",
+ "msg": "Aggregator is closed. Illegal action."
+ },
+ {
+ "code": 6016,
+ "name": "IllegalOracleIdxError",
+ "msg": "Illegal oracle index."
+ },
+ {
+ "code": 6017,
+ "name": "OracleAlreadyRespondedError",
+ "msg": "The provided oracle has already responded this round."
+ },
+ {
+ "code": 6018,
+ "name": "ProtoDeserializeError",
+ "msg": "Failed to deserialize protocol buffer."
+ },
+ {
+ "code": 6019,
+ "name": "UnauthorizedStateUpdateError",
+ "msg": "Unauthorized program state modification attempted."
+ },
+ {
+ "code": 6020,
+ "name": "MissingOracleAccountsError",
+ "msg": "Not enough oracle accounts provided to closeRounds."
+ },
+ {
+ "code": 6021,
+ "name": "OracleMismatchError",
+ "msg": "An unexpected oracle account was provided for the transaction."
+ },
+ {
+ "code": 6022,
+ "name": "CrankMaxCapacityError",
+ "msg": "Attempted to push to a Crank that's at capacity"
+ },
+ {
+ "code": 6023,
+ "name": "AggregatorLeaseInsufficientFunds",
+ "msg": "Aggregator update call attempted but attached lease has insufficient funds."
+ },
+ {
+ "code": 6024,
+ "name": "IncorrectTokenAccountMint",
+ "msg": "The provided token account does not point to the Switchboard token mint."
+ },
+ {
+ "code": 6025,
+ "name": "InvalidEscrowAccount",
+ "msg": "An invalid escrow account was provided."
+ },
+ {
+ "code": 6026,
+ "name": "CrankEmptyError",
+ "msg": "Crank empty. Pop failed."
+ },
+ {
+ "code": 6027,
+ "name": "PdaDeriveError",
+ "msg": "Failed to derive a PDA from the provided seed."
+ },
+ {
+ "code": 6028,
+ "name": "AggregatorAccountNotFound",
+ "msg": "Aggregator account missing from provided account list."
+ },
+ {
+ "code": 6029,
+ "name": "PermissionAccountNotFound",
+ "msg": "Permission account missing from provided account list."
+ },
+ {
+ "code": 6030,
+ "name": "LeaseAccountDeriveFailure",
+ "msg": "Failed to derive a lease account."
+ },
+ {
+ "code": 6031,
+ "name": "PermissionAccountDeriveFailure",
+ "msg": "Failed to derive a permission account."
+ },
+ {
+ "code": 6032,
+ "name": "EscrowAccountNotFound",
+ "msg": "Escrow account missing from provided account list."
+ },
+ {
+ "code": 6033,
+ "name": "LeaseAccountNotFound",
+ "msg": "Lease account missing from provided account list."
+ },
+ {
+ "code": 6034,
+ "name": "DecimalConversionError",
+ "msg": "Decimal conversion method failed."
+ },
+ {
+ "code": 6035,
+ "name": "PermissionDenied",
+ "msg": "Permission account is missing required flags for the given action."
+ },
+ {
+ "code": 6036,
+ "name": "QueueAtCapacity",
+ "msg": "Oracle queue is at lease capacity."
+ },
+ {
+ "code": 6037,
+ "name": "ExcessiveCrankRowsError",
+ "msg": "Data feed is already pushed on a crank."
+ },
+ {
+ "code": 6038,
+ "name": "AggregatorLockedError",
+ "msg": "Aggregator is locked, no setting modifications or job additions allowed."
+ },
+ {
+ "code": 6039,
+ "name": "AggregatorInvalidBatchSizeError",
+ "msg": "Aggregator invalid batch size."
+ },
+ {
+ "code": 6040,
+ "name": "AggregatorJobChecksumMismatch",
+ "msg": "Oracle provided an incorrect aggregator job checksum."
+ },
+ {
+ "code": 6041,
+ "name": "IntegerOverflowError",
+ "msg": "An integer overflow occurred."
+ },
+ {
+ "code": 6042,
+ "name": "InvalidUpdatePeriodError",
+ "msg": "Minimum update period is 5 seconds."
+ },
+ {
+ "code": 6043,
+ "name": "NoResultsError",
+ "msg": "Aggregator round evaluation attempted with no results."
+ },
+ {
+ "code": 6044,
+ "name": "InvalidExpirationError",
+ "msg": "An expiration constraint was broken."
+ },
+ {
+ "code": 6045,
+ "name": "InsufficientStakeError",
+ "msg": "An account provided insufficient stake for action."
+ },
+ {
+ "code": 6046,
+ "name": "LeaseInactiveError",
+ "msg": "The provided lease account is not active."
+ },
+ {
+ "code": 6047,
+ "name": "NoAggregatorJobsFound",
+ "msg": "No jobs are currently included in the aggregator."
+ },
+ {
+ "code": 6048,
+ "name": "IntegerUnderflowError",
+ "msg": "An integer underflow occurred."
+ },
+ {
+ "code": 6049,
+ "name": "OracleQueueMismatch",
+ "msg": "An invalid oracle queue account was provided."
+ },
+ {
+ "code": 6050,
+ "name": "OracleWalletMismatchError",
+ "msg": "An unexpected oracle wallet account was provided for the transaction."
+ },
+ {
+ "code": 6051,
+ "name": "InvalidBufferAccountError",
+ "msg": "An invalid buffer account was provided."
+ },
+ {
+ "code": 6052,
+ "name": "InsufficientOracleQueueError",
+ "msg": "Insufficient oracle queue size."
+ },
+ {
+ "code": 6053,
+ "name": "InvalidAuthorityError",
+ "msg": "Invalid authority account provided."
+ },
+ {
+ "code": 6054,
+ "name": "InvalidTokenAccountMintError",
+ "msg": "A provided token wallet is associated with an incorrect mint."
+ },
+ {
+ "code": 6055,
+ "name": "ExcessiveLeaseWithdrawlError",
+ "msg": "You must leave enough funds to perform at least 1 update in the lease."
+ },
+ {
+ "code": 6056,
+ "name": "InvalideHistoryAccountError",
+ "msg": "Invalid history account provided."
+ },
+ {
+ "code": 6057,
+ "name": "InvalidLeaseAccountEscrowError",
+ "msg": "Invalid lease account escrow."
+ },
+ {
+ "code": 6058,
+ "name": "InvalidCrankAccountError",
+ "msg": "Invalid crank provided."
+ },
+ {
+ "code": 6059,
+ "name": "CrankNoElementsReadyError",
+ "msg": "No elements ready to be popped."
+ },
+ {
+ "code": 6060,
+ "name": "IndexOutOfBoundsError",
+ "msg": "Index out of bounds"
+ },
+ {
+ "code": 6061,
+ "name": "VrfInvalidRequestError",
+ "msg": "Invalid vrf request params"
+ },
+ {
+ "code": 6062,
+ "name": "VrfInvalidProofSubmissionError",
+ "msg": "Vrf proof failed to verify"
+ },
+ {
+ "code": 6063,
+ "name": "VrfVerifyError",
+ "msg": "Error in verifying vrf proof."
+ },
+ {
+ "code": 6064,
+ "name": "VrfCallbackError",
+ "msg": "Vrf callback function failed."
+ },
+ {
+ "code": 6065,
+ "name": "VrfCallbackParamsError",
+ "msg": "Invalid vrf callback params provided."
+ },
+ {
+ "code": 6066,
+ "name": "VrfCallbackAlreadyCalledError",
+ "msg": "Vrf callback has already been triggered."
+ },
+ {
+ "code": 6067,
+ "name": "VrfInvalidPubkeyError",
+ "msg": "The provided pubkey is invalid to use in ecvrf proofs"
+ },
+ {
+ "code": 6068,
+ "name": "VrfTooManyVerifyCallsError",
+ "msg": "Number of required verify calls exceeded"
+ },
+ {
+ "code": 6069,
+ "name": "VrfRequestAlreadyLaunchedError",
+ "msg": "Vrf request is already pending"
+ },
+ {
+ "code": 6070,
+ "name": "VrfInsufficientVerificationError",
+ "msg": "Insufficient amount of proofs collected for VRF callback"
+ },
+ {
+ "code": 6071,
+ "name": "InvalidVrfProducerError",
+ "msg": "An incorrect oracle attempted to submit a proof"
+ },
+ {
+ "code": 6072,
+ "name": "NoopError",
+ "msg": "Noop error"
+ }
+ ]
+}
diff --git a/basics/anchorpy-main/tests/idls/sysvars.json b/basics/anchorpy-main/tests/idls/sysvars.json
new file mode 100644
index 0000000..11d7c4b
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/sysvars.json
@@ -0,0 +1,27 @@
+{
+ "version": "0.0.0",
+ "name": "sysvars",
+ "instructions": [
+ {
+ "name": "sysvars",
+ "accounts": [
+ {
+ "name": "clock",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "rent",
+ "isMut": false,
+ "isSigner": false
+ },
+ {
+ "name": "stakeHistory",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/idls/tictactoe.json b/basics/anchorpy-main/tests/idls/tictactoe.json
new file mode 100644
index 0000000..507f863
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/tictactoe.json
@@ -0,0 +1,179 @@
+{
+ "version": "0.1.0",
+ "name": "tic_tac_toe",
+ "instructions": [
+ {
+ "name": "setupGame",
+ "accounts": [
+ {
+ "name": "game",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "playerOne",
+ "isMut": true,
+ "isSigner": true
+ },
+ {
+ "name": "systemProgram",
+ "isMut": false,
+ "isSigner": false
+ }
+ ],
+ "args": [
+ {
+ "name": "playerTwo",
+ "type": "publicKey"
+ }
+ ]
+ },
+ {
+ "name": "play",
+ "accounts": [
+ {
+ "name": "game",
+ "isMut": true,
+ "isSigner": false
+ },
+ {
+ "name": "player",
+ "isMut": false,
+ "isSigner": true
+ }
+ ],
+ "args": [
+ {
+ "name": "tile",
+ "type": {
+ "defined": "Tile"
+ }
+ }
+ ]
+ }
+ ],
+ "accounts": [
+ {
+ "name": "Game",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "players",
+ "type": {
+ "array": ["publicKey", 2]
+ }
+ },
+ {
+ "name": "turn",
+ "type": "u8"
+ },
+ {
+ "name": "board",
+ "type": {
+ "array": [
+ {
+ "array": [
+ {
+ "option": {
+ "defined": "Sign"
+ }
+ },
+ 3
+ ]
+ },
+ 3
+ ]
+ }
+ },
+ {
+ "name": "state",
+ "type": {
+ "defined": "GameState"
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "types": [
+ {
+ "name": "Tile",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "row",
+ "type": "u8"
+ },
+ {
+ "name": "column",
+ "type": "u8"
+ }
+ ]
+ }
+ },
+ {
+ "name": "GameState",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "Active"
+ },
+ {
+ "name": "Tie"
+ },
+ {
+ "name": "Won",
+ "fields": [
+ {
+ "name": "winner",
+ "type": "publicKey"
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "Sign",
+ "type": {
+ "kind": "enum",
+ "variants": [
+ {
+ "name": "X"
+ },
+ {
+ "name": "O"
+ }
+ ]
+ }
+ }
+ ],
+ "errors": [
+ {
+ "code": 6000,
+ "name": "TileOutOfBounds"
+ },
+ {
+ "code": 6001,
+ "name": "TileAlreadySet"
+ },
+ {
+ "code": 6002,
+ "name": "GameAlreadyOver"
+ },
+ {
+ "code": 6003,
+ "name": "NotPlayersTurn"
+ },
+ {
+ "code": 6004,
+ "name": "GameAlreadyStarted"
+ }
+ ],
+ "metadata": {
+ "address": "4V6T2muqU1mHSg5XfK3SMgxZWQRSEUh72LzwGTLHGzsY"
+ }
+}
diff --git a/basics/anchorpy-main/tests/idls/typescript.json b/basics/anchorpy-main/tests/idls/typescript.json
new file mode 100644
index 0000000..6aa06ab
--- /dev/null
+++ b/basics/anchorpy-main/tests/idls/typescript.json
@@ -0,0 +1,11 @@
+{
+ "version": "0.0.0",
+ "name": "typescript",
+ "instructions": [
+ {
+ "name": "initialize",
+ "accounts": [],
+ "args": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basics/anchorpy-main/tests/test_basic_0.py b/basics/anchorpy-main/tests/test_basic_0.py
new file mode 100644
index 0000000..6d176ad
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_basic_0.py
@@ -0,0 +1,22 @@
+"""Mimics anchor/examples/tutorial/basic-0/tests/basic-0.js."""
+from pathlib import Path
+
+from anchorpy import create_workspace
+from anchorpy.pytest_plugin import localnet_fixture
+from pytest import mark
+
+PATH = Path("anchor/examples/tutorial/basic-0")
+
+# We use localnet_fixture here to make sure it works, but use
+# workspace_fixture elsewhere.
+localnet = localnet_fixture(PATH)
+
+
+@mark.asyncio
+async def test_init(localnet) -> None:
+ """Test that the initialize function is invoked successfully."""
+ workspace = create_workspace(PATH)
+ program = workspace["basic_0"]
+ res = await program.rpc["initialize"]()
+ assert res
+ await program.close()
diff --git a/basics/anchorpy-main/tests/test_basic_1.py b/basics/anchorpy-main/tests/test_basic_1.py
new file mode 100644
index 0000000..43be062
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_basic_1.py
@@ -0,0 +1,61 @@
+"""Mimics anchor/examples/tutorial/basic-1."""
+
+from anchorpy import Context, Program
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from pytest import fixture, mark
+from pytest_asyncio import fixture as async_fixture
+from solders.keypair import Keypair
+from solders.system_program import ID as SYS_PROGRAM_ID
+
+workspace = workspace_fixture(
+ "anchor/examples/tutorial/basic-1", build_cmd="anchor build --skip-lint"
+)
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ """Create a Program instance."""
+ return workspace["basic_1"]
+
+
+@async_fixture(scope="module")
+async def initialized_account(program: Program) -> Keypair:
+ """Generate a keypair and initialize it."""
+ my_account = Keypair()
+ await program.rpc["initialize"](
+ 1234,
+ ctx=Context(
+ accounts={
+ "my_account": my_account.pubkey(),
+ "user": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[my_account],
+ ),
+ )
+ return my_account
+
+
+@mark.asyncio
+async def test_create_and_initialize_account(
+ program: Program,
+ initialized_account: Keypair,
+) -> None:
+ """Test creating and initializing account in single tx."""
+ account = await program.account["MyAccount"].fetch(initialized_account.pubkey())
+ assert account.data == 1234
+
+
+@mark.asyncio
+async def test_update_previously_created_account(
+ initialized_account: Keypair,
+ program: Program,
+) -> None:
+ """Test updating a previously created account."""
+ await program.rpc["update"](
+ 4321,
+ ctx=Context(accounts={"my_account": initialized_account.pubkey()}),
+ )
+ account = await program.account["MyAccount"].fetch(initialized_account.pubkey())
+ assert account.data == 4321
diff --git a/basics/anchorpy-main/tests/test_basic_2.py b/basics/anchorpy-main/tests/test_basic_2.py
new file mode 100644
index 0000000..0524633
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_basic_2.py
@@ -0,0 +1,73 @@
+"""Mimics anchor/examples/tutorial/basic-2/tests/basic-2.js."""
+
+from anchorpy import Context, Program, Provider
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from pytest import fixture, mark
+from pytest_asyncio import fixture as async_fixture
+from solders.keypair import Keypair
+from solders.system_program import ID as SYS_PROGRAM_ID
+
+workspace = workspace_fixture("anchor/examples/tutorial/basic-2")
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ """Create a Program instance."""
+ return workspace["basic_2"]
+
+
+@fixture(scope="module")
+def provider(program: Program) -> Provider:
+ """Get a Provider instance."""
+ return program.provider
+
+
+@async_fixture(scope="module")
+async def created_counter(program: Program, provider: Provider) -> Keypair:
+ """Create the counter."""
+ counter = Keypair()
+ await program.rpc["create"](
+ provider.wallet.public_key,
+ ctx=Context(
+ accounts={
+ "counter": counter.pubkey(),
+ "user": provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[counter],
+ ),
+ )
+ return counter
+
+
+@mark.asyncio
+async def test_create_counter(
+ created_counter: Keypair,
+ program: Program,
+ provider: Provider,
+) -> None:
+ """Test creating a counter."""
+ counter_account = await program.account["Counter"].fetch(created_counter.pubkey())
+ assert counter_account.authority == provider.wallet.public_key
+ assert counter_account.count == 0
+
+
+@mark.asyncio
+async def test_update_counter(
+ created_counter: Keypair,
+ program: Program,
+ provider: Provider,
+) -> None:
+ """Test updating the counter."""
+ await program.rpc["increment"](
+ ctx=Context(
+ accounts={
+ "counter": created_counter.pubkey(),
+ "authority": provider.wallet.public_key,
+ },
+ ),
+ )
+ counter_account = await program.account["Counter"].fetch(created_counter.pubkey())
+ assert counter_account.authority == provider.wallet.public_key
+ assert counter_account.count == 1
diff --git a/basics/anchorpy-main/tests/test_basic_3.py b/basics/anchorpy-main/tests/test_basic_3.py
new file mode 100644
index 0000000..b87b089
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_basic_3.py
@@ -0,0 +1,49 @@
+"""Mimics anchor/examples/tutorial/basic-3/tests/basic-3.js."""
+from typing import AsyncGenerator
+
+from anchorpy import Context, Provider
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from pytest import mark
+from pytest_asyncio import fixture as async_fixture
+from solders.keypair import Keypair
+from solders.system_program import ID as SYS_PROGRAM_ID
+
+workspace = workspace_fixture("anchor/examples/tutorial/basic-3")
+
+
+@async_fixture(scope="module")
+async def provider() -> AsyncGenerator[Provider, None]:
+ """Create a Provider instance."""
+ prov = Provider.local()
+ yield prov
+ await prov.close()
+
+
+@mark.asyncio
+async def test_cpi(workspace: WorkspaceType, provider: Provider) -> None:
+ """Test CPI from puppet master to puppet."""
+ puppet_master = workspace["puppet_master"]
+ puppet = workspace["puppet"]
+ new_puppet_account = Keypair()
+ await puppet.rpc["initialize"](
+ ctx=Context(
+ accounts={
+ "puppet": new_puppet_account.pubkey(),
+ "user": provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[new_puppet_account],
+ ),
+ )
+ await puppet_master.rpc["pull_strings"](
+ 111,
+ ctx=Context(
+ accounts={
+ "puppet": new_puppet_account.pubkey(),
+ "puppet_program": puppet.program_id,
+ },
+ ),
+ )
+ puppet_account = await puppet.account["Data"].fetch(new_puppet_account.pubkey())
+ assert puppet_account.data == 111
diff --git a/basics/anchorpy-main/tests/test_basic_3_bankrun.py b/basics/anchorpy-main/tests/test_basic_3_bankrun.py
new file mode 100644
index 0000000..2ba38a1
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_basic_3_bankrun.py
@@ -0,0 +1,63 @@
+"""Mimics anchor/examples/tutorial/basic-3/tests/basic-3.js."""
+from pathlib import Path
+from typing import AsyncGenerator
+
+from anchorpy import Context
+from anchorpy.pytest_plugin import bankrun_fixture
+from anchorpy.workspace import WorkspaceType, close_workspace, create_workspace
+from pytest import mark
+from pytest_asyncio import fixture as async_fixture
+from solders.bankrun import ProgramTestContext
+from solders.keypair import Keypair
+from solders.system_program import ID as SYS_PROGRAM_ID
+
+PATH = Path("anchor/examples/tutorial/basic-3")
+
+bankrun = bankrun_fixture(PATH)
+
+
+@async_fixture(scope="module")
+async def workspace(bankrun: ProgramTestContext) -> AsyncGenerator[WorkspaceType, None]:
+ ws = create_workspace(PATH)
+ yield ws
+ await close_workspace(ws)
+
+
+@mark.asyncio
+async def test_cpi(workspace: WorkspaceType, bankrun: ProgramTestContext) -> None:
+ """Test CPI from puppet master to puppet."""
+ puppet_master = workspace["puppet_master"]
+ puppet = workspace["puppet"]
+ new_puppet_account = Keypair()
+ payer = bankrun.payer
+ blockhash = bankrun.last_blockhash
+ client = bankrun.banks_client
+ tx0 = puppet.transaction["initialize"](
+ payer=payer,
+ blockhash=blockhash,
+ ctx=Context(
+ accounts={
+ "puppet": new_puppet_account.pubkey(),
+ "user": payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[new_puppet_account],
+ ),
+ )
+ await client.process_transaction(tx0)
+ tx1 = puppet_master.transaction["pull_strings"](
+ 111,
+ payer=payer,
+ blockhash=blockhash,
+ ctx=Context(
+ accounts={
+ "puppet": new_puppet_account.pubkey(),
+ "puppet_program": puppet.program_id,
+ },
+ ),
+ )
+ await client.process_transaction(tx1)
+ puppet_account_raw = await client.get_account(new_puppet_account.pubkey())
+ assert puppet_account_raw is not None
+ decoded = puppet.account["Data"].coder.accounts.decode(puppet_account_raw.data)
+ assert decoded.data == 111
diff --git a/basics/anchorpy-main/tests/test_chat.py b/basics/anchorpy-main/tests/test_chat.py
new file mode 100644
index 0000000..8af7c17
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_chat.py
@@ -0,0 +1,130 @@
+import random
+import string
+
+from anchorpy import Context, Program, Provider
+from anchorpy.pytest_plugin import workspace_fixture
+from pytest import fixture, mark
+from pytest_asyncio import fixture as async_fixture
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.sysvar import RENT
+
+workspace = workspace_fixture(
+ "anchor/tests/chat/", build_cmd="anchor build --skip-lint"
+)
+
+
+@fixture(scope="module")
+def program(workspace) -> Program:
+ """Create a Program instance."""
+ return workspace["chat"]
+
+
+@fixture(scope="module")
+async def provider(program: Program) -> Provider:
+ """Get a Provider instance."""
+ return program.provider
+
+
+@async_fixture(scope="module")
+async def created_chatroom(program: Program) -> Keypair:
+ chatroom = Keypair()
+ await program.rpc["create_chat_room"](
+ "Test Chat",
+ ctx=Context(
+ accounts={
+ "chat_room": chatroom.pubkey(),
+ "rent": RENT,
+ },
+ pre_instructions=[
+ await program.account["ChatRoom"].create_instruction(chatroom),
+ ],
+ signers=[chatroom],
+ ),
+ )
+ return chatroom
+
+
+@async_fixture(scope="module")
+async def created_user(
+ created_chatroom: Keypair, program: Program
+) -> tuple[Pubkey, Pubkey]:
+ authority = program.provider.wallet.public_key
+ user, bump = Pubkey.find_program_address([bytes(authority)], program.program_id)
+ await program.rpc["create_user"](
+ "My User",
+ ctx=Context(
+ accounts={
+ "user": user,
+ "authority": authority,
+ "system_program": SYS_PROGRAM_ID,
+ }
+ ),
+ )
+ return user, authority
+
+
+@async_fixture(scope="module")
+async def sent_messages(
+ created_user: tuple[Pubkey, Pubkey],
+ created_chatroom: Keypair,
+ program: Program,
+) -> list[str]:
+ user, authority = created_user
+ num_messages = 10
+ to_choose = string.ascii_uppercase + string.digits
+ messages = ["".join(random.choices(to_choose, k=13)) for _ in range(num_messages)]
+ for i, msg in enumerate(messages):
+ print(f"sending message {i}")
+ await program.rpc["send_message"](
+ msg,
+ ctx=Context(
+ accounts={
+ "user": user,
+ "authority": authority,
+ "chat_room": created_chatroom.pubkey(),
+ },
+ ),
+ )
+ return messages
+
+
+@mark.asyncio
+async def test_created_chatroom(created_chatroom: Keypair, program: Program) -> None:
+ chat = await program.account["ChatRoom"].fetch(created_chatroom.pubkey())
+ name = bytes(chat.name).rstrip(b"\x00").decode("utf-8")
+ assert name == "Test Chat"
+ assert len(chat.messages) == 33607
+ assert chat.head == 0
+ assert chat.tail == 0
+
+
+@mark.asyncio
+async def test_created_user(
+ created_user: tuple[Pubkey, Pubkey],
+ program: Program,
+) -> None:
+ user, authority = created_user
+ account = await program.account["User"].fetch(user)
+ assert account.name == "My User"
+ assert account.authority == authority
+
+
+@mark.asyncio
+async def test_sent_messages(
+ program: Program,
+ created_chatroom: Keypair,
+ sent_messages: list[str],
+ created_user: tuple[Pubkey, Pubkey],
+) -> None:
+ user, _ = created_user
+ chat = await program.account["ChatRoom"].fetch(created_chatroom.pubkey())
+ for i, msg in enumerate(chat.messages):
+ if i < len(sent_messages):
+ data = bytes(msg.data).rstrip(b"\x00").decode("utf-8")
+ print(f"Message {data}")
+ assert msg.from_ == user
+ assert data == sent_messages[i]
+ else:
+ assert msg.data == [0] * 280
diff --git a/basics/anchorpy-main/tests/test_cli.py b/basics/anchorpy-main/tests/test_cli.py
new file mode 100644
index 0000000..7e964de
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_cli.py
@@ -0,0 +1,29 @@
+"""Test that the CLI commands work."""
+
+from pathlib import Path
+
+from anchorpy import localnet_fixture
+from anchorpy.cli import app
+from solana.rpc.api import Client
+from solana.rpc.commitment import Processed
+from solders.signature import Signature
+from typer.testing import CliRunner
+
+PATH = Path("anchor/examples/tutorial/basic-0")
+
+localnet = localnet_fixture(PATH)
+
+runner = CliRunner()
+
+
+def test_shell(localnet, monkeypatch) -> None:
+ monkeypatch.chdir("anchor/examples/tutorial/basic-0")
+ cli_input = "await workspace['basic_0'].rpc['initialize']()\nexit()"
+ result = runner.invoke(app, ["shell"], input=cli_input)
+ assert result.exit_code == 0
+ assert "Hint: type `workspace`" in result.stdout
+ tx_sig = Signature.from_string(
+ result.stdout.split("Out[1]: \n")[1].split("\n ")[1].split(",")[0]
+ )
+ client = Client()
+ client.confirm_transaction(tx_sig, commitment=Processed)
diff --git a/basics/anchorpy-main/tests/test_cli_init.py b/basics/anchorpy-main/tests/test_cli_init.py
new file mode 100644
index 0000000..84aed56
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_cli_init.py
@@ -0,0 +1,25 @@
+import subprocess
+from pathlib import Path
+
+from pytest import fixture
+
+PATH = Path("anchor/examples/tutorial/basic-0")
+PROJECT_NAME = "foo"
+
+
+@fixture(scope="session")
+def project_parent_dir(tmpdir_factory) -> Path:
+ return Path(tmpdir_factory.mktemp("temp"))
+
+
+@fixture(scope="session")
+def project_dir(project_parent_dir: Path) -> Path:
+ subprocess.run(["anchor", "init", PROJECT_NAME], cwd=project_parent_dir, check=True)
+ proj_dir = project_parent_dir / PROJECT_NAME
+ subprocess.run(["anchor", "build"], cwd=proj_dir, check=True)
+ subprocess.run(["anchorpy", "init", PROJECT_NAME], cwd=proj_dir, check=True)
+ return proj_dir
+
+
+def test_init(project_dir: Path):
+ subprocess.run("pytest", cwd=project_dir, check=True)
diff --git a/basics/anchorpy-main/tests/test_composite.py b/basics/anchorpy-main/tests/test_composite.py
new file mode 100644
index 0000000..a1e70ce
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_composite.py
@@ -0,0 +1,70 @@
+"""Mimics anchor/tests/composite/tests/composite.js."""
+from anchorpy import Context, Program
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from pytest import fixture, mark
+from pytest_asyncio import fixture as async_fixture
+from solders.keypair import Keypair
+from solders.sysvar import RENT
+
+workspace = workspace_fixture(
+ "anchor/tests/composite/", build_cmd="anchor build --skip-lint"
+)
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ """Create a Program instance."""
+ return workspace["composite"]
+
+
+@async_fixture(scope="module")
+async def initialized_accounts(program: Program) -> tuple[Keypair, Keypair]:
+ """Generate keypairs and use them when callling the initialize function."""
+ dummy_a = Keypair()
+ dummy_b = Keypair()
+ await program.rpc["initialize"](
+ ctx=Context(
+ accounts={
+ "dummy_a": dummy_a.pubkey(),
+ "dummy_b": dummy_b.pubkey(),
+ "rent": RENT,
+ },
+ signers=[dummy_a, dummy_b],
+ pre_instructions=[
+ await program.account["DummyA"].create_instruction(dummy_a),
+ await program.account["DummyB"].create_instruction(dummy_b),
+ ],
+ ),
+ )
+ return dummy_a, dummy_b
+
+
+@async_fixture(scope="module")
+async def composite_updated_accounts(
+ program: Program,
+ initialized_accounts: tuple[Keypair, Keypair],
+) -> tuple[Keypair, Keypair]:
+ """Run composite_update and return the keypairs used."""
+ dummy_a, dummy_b = initialized_accounts
+ ctx = Context(
+ accounts={
+ "foo": {"dummy_a": dummy_a.pubkey()},
+ "bar": {"dummy_b": dummy_b.pubkey()},
+ },
+ )
+ await program.rpc["composite_update"](1234, 4321, ctx=ctx)
+ return initialized_accounts
+
+
+@mark.asyncio
+async def test_composite_update(
+ program: Program,
+ composite_updated_accounts: tuple[Keypair, Keypair],
+) -> None:
+ """Test that the call to composite_update worked."""
+ dummy_a, dummy_b = composite_updated_accounts
+ dummy_a_account = await program.account["DummyA"].fetch(dummy_a.pubkey())
+ dummy_b_account = await program.account["DummyB"].fetch(dummy_b.pubkey())
+ assert dummy_a_account.data == 1234
+ assert dummy_b_account.data == 4321
diff --git a/basics/anchorpy-main/tests/test_errors.py b/basics/anchorpy-main/tests/test_errors.py
new file mode 100644
index 0000000..5ab5721
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_errors.py
@@ -0,0 +1,139 @@
+"""Mimics anchor/tests/errors/tests/errors.js."""
+from anchorpy import Context, Program
+from anchorpy.error import ProgramError
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from pytest import fixture, mark, raises
+from solana.rpc.core import RPCNoResultException
+from solana.transaction import Transaction
+from solders.instruction import AccountMeta, Instruction
+from solders.keypair import Keypair
+from solders.sysvar import RENT
+
+workspace = workspace_fixture(
+ "anchor/tests/errors/", build_cmd="anchor build --skip-lint"
+)
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ return workspace["errors"]
+
+
+@mark.asyncio
+async def test_hello_err(program: Program) -> None:
+ """Test error from hello func."""
+ with raises(ProgramError) as excinfo:
+ await program.rpc["hello"]()
+ assert excinfo.value.code == 6000
+ expected_msg = "This is an error message clients will automatically display"
+ assert excinfo.value.msg == expected_msg
+ assert expected_msg in str(excinfo)
+ assert excinfo.value.logs
+
+
+@mark.asyncio
+async def test_hello_no_msg_err(program: Program) -> None:
+ """Test error from helloNoMsg func."""
+ with raises(ProgramError) as excinfo:
+ await program.rpc["hello_no_msg"]()
+ assert excinfo.value.msg == "HelloNoMsg"
+ assert excinfo.value.code == 6000 + 123
+ assert excinfo.value.logs
+
+
+@mark.asyncio
+async def test_hello_next_err(program: Program) -> None:
+ """Test error from helloNext func."""
+ with raises(ProgramError) as excinfo:
+ await program.rpc["hello_next"]()
+ assert excinfo.value.msg == "HelloNext"
+ assert excinfo.value.code == 6000 + 124
+ assert excinfo.value.logs
+
+
+@mark.asyncio
+async def test_mut_err(program: Program) -> None:
+ """Test mmut error."""
+ with raises(ProgramError) as excinfo:
+ await program.rpc["mut_error"](ctx=Context(accounts={"my_account": RENT}))
+ assert excinfo.value.msg == "A mut constraint was violated"
+ assert excinfo.value.code == 2000
+ assert excinfo.value.logs
+
+
+@mark.asyncio
+async def test_has_one_err(program: Program) -> None:
+ """Test hasOneError."""
+ account = Keypair()
+ with raises(ProgramError) as excinfo:
+ await program.rpc["has_one_error"](
+ ctx=Context(
+ accounts={
+ "my_account": account.pubkey(),
+ "owner": RENT,
+ "rent": RENT,
+ },
+ pre_instructions=[
+ await program.account["HasOneAccount"].create_instruction(account)
+ ],
+ signers=[account],
+ )
+ )
+ assert excinfo.value.msg == "A has_one constraint was violated"
+ assert excinfo.value.code == 2001
+ assert excinfo.value.logs
+
+
+@mark.asyncio
+async def test_signer_err(program: Program) -> None:
+ """Test signer error."""
+ tx = Transaction()
+ tx.add(
+ Instruction(
+ accounts=[
+ AccountMeta(
+ pubkey=RENT,
+ is_writable=False,
+ is_signer=False,
+ ),
+ ],
+ program_id=program.program_id,
+ data=program.coder.instruction.encode("signer_error", {}),
+ ),
+ )
+ with raises(RPCNoResultException):
+ await program.provider.send(tx)
+
+
+@mark.asyncio
+async def test_raw_custom_err(program: Program) -> None:
+ with raises(ProgramError) as excinfo:
+ await program.rpc["raw_custom_error"](
+ ctx=Context(
+ accounts={
+ "my_account": RENT,
+ },
+ )
+ )
+ assert excinfo.value.msg == "HelloCustom"
+ assert excinfo.value.code == 6000 + 125
+ assert excinfo.value.logs
+
+
+@mark.asyncio
+async def test_account_not_initialised_err(program: Program) -> None:
+ with raises(ProgramError) as excinfo:
+ await program.rpc["account_not_initialized_error"](
+ ctx=Context(
+ accounts={
+ "not_initialized_account": Keypair().pubkey(),
+ },
+ )
+ )
+ assert (
+ excinfo.value.msg
+ == "The program expected this account to be already initialized"
+ )
+ assert excinfo.value.code == 3012
+ assert excinfo.value.logs
diff --git a/basics/anchorpy-main/tests/test_events.py b/basics/anchorpy-main/tests/test_events.py
new file mode 100644
index 0000000..3cf25dd
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_events.py
@@ -0,0 +1,43 @@
+"""Mimics anchor/tests/errors/tests/events.js.
+
+Note: this is unfinished.
+"""
+from typing import cast
+
+from anchorpy import (
+ EventParser,
+ Program,
+)
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from pytest import fixture, mark
+from solana.rpc.websocket_api import SolanaWsClientProtocol, connect
+from solders.rpc.config import RpcTransactionLogsFilter
+from solders.rpc.responses import LogsNotification
+
+workspace = workspace_fixture(
+ "anchor/tests/events/", build_cmd="anchor build --skip-lint"
+)
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ return workspace["events"]
+
+
+@mark.asyncio
+async def test_initialize(program: Program) -> None:
+ async with cast(SolanaWsClientProtocol, connect()) as websocket: # type: ignore
+ await websocket.logs_subscribe(RpcTransactionLogsFilter.All)
+ await websocket.recv()
+ await program.rpc["initialize"]()
+ received = await websocket.recv()
+ first = received[0]
+ assert isinstance(first, LogsNotification)
+ logs = first.result.value.logs
+ parser = EventParser(program.program_id, program.coder)
+ parsed = []
+ parser.parse_logs(logs, lambda evt: parsed.append(evt))
+ event = parsed[0]
+ assert event.data.data == 5
+ assert event.data.label == "hello"
diff --git a/basics/anchorpy-main/tests/test_misc.py b/basics/anchorpy-main/tests/test_misc.py
new file mode 100644
index 0000000..56a5458
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_misc.py
@@ -0,0 +1,234 @@
+"""Mimics anchor/tests/misc/tests/misc.js."""
+import asyncio
+import subprocess
+from pathlib import Path
+
+from anchorpy import Context, Program
+from anchorpy.error import ProgramError
+from anchorpy.provider import Provider, Wallet
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.utils.rpc import invoke
+from anchorpy.workspace import WorkspaceType
+from anchorpy_core.idl import IdlConst, IdlTypeSimple
+from pytest import fixture, mark, raises
+from pytest_asyncio import fixture as async_fixture
+from solana.rpc.core import RPCNoResultException
+from solana.rpc.types import MemcmpOpts
+from solders.keypair import Keypair
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.sysvar import RENT
+
+PATH = Path("anchor/tests/misc/")
+# bankrun = bankrun_fixture(PATH, build_cmd="anchor build --skip-lint")
+workspace = workspace_fixture(PATH, build_cmd="anchor build --skip-lint")
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ return workspace["misc"]
+
+
+def test_idl_constants(program: Program) -> None:
+ idl_constants = program.idl.constants
+ assert idl_constants == [
+ IdlConst(name="BASE", ty=IdlTypeSimple.U128, value="1_000_000"),
+ IdlConst(name="DECIMALS", ty=IdlTypeSimple.U8, value="6"),
+ ]
+
+
+def test_methods(program: Program, initialized_keypair: Keypair) -> None:
+ ix_from_methods = (
+ program.methods["test_close"]
+ .accounts(
+ {
+ "data": initialized_keypair.pubkey(),
+ "sol_dest": initialized_keypair.pubkey(),
+ }
+ )
+ .instruction()
+ )
+ ix_legacy = program.instruction["test_close"](
+ ctx=Context(
+ accounts={
+ "data": initialized_keypair.pubkey(),
+ "sol_dest": initialized_keypair.pubkey(),
+ },
+ )
+ )
+ assert ix_from_methods == ix_legacy
+
+
+@mark.asyncio
+async def test_at_constructor(program: Program) -> None:
+ """Test that the Program.at classmethod works."""
+ idl_path = "target/idl/misc.json"
+ subprocess.run(
+ ["anchor", "idl", "init", "-f", idl_path, str(program.program_id)],
+ cwd=PATH,
+ )
+ fetched = await program.at(program.program_id, program.provider)
+ await fetched.close()
+ assert fetched.idl.name == "misc"
+
+
+@async_fixture(scope="module")
+async def initialized_keypair(program: Program) -> Keypair:
+ data = Keypair()
+ await program.rpc["initialize"](
+ 1234,
+ 22,
+ ctx=Context(
+ accounts={"data": data.pubkey(), "rent": RENT},
+ signers=[data],
+ pre_instructions=[await program.account["Data"].create_instruction(data)],
+ ),
+ )
+ return data
+
+
+@mark.asyncio
+async def test_readonly_provider(
+ program: Program, initialized_keypair: Keypair
+) -> None:
+ async with Provider.readonly() as provider:
+ readonly_program = Program(program.idl, program.program_id, provider=provider)
+ data_account = await readonly_program.account["Data"].fetch(
+ initialized_keypair.pubkey()
+ )
+ assert data_account.udata == 1234
+ assert data_account.idata == 22
+
+
+@mark.asyncio
+async def test_fetch_multiple(program: Program, initialized_keypair: Keypair) -> None:
+ batch_size = 2
+ n_accounts = batch_size * 100 + 1
+ data_account = await program.account["Data"].fetch(initialized_keypair.pubkey())
+ pubkeys = [initialized_keypair.pubkey()] * n_accounts
+ data_accounts = await program.account["Data"].fetch_multiple(
+ pubkeys, batch_size=batch_size
+ )
+ assert len(data_accounts) == n_accounts
+ assert all(acc == data_account for acc in data_accounts)
+
+
+@mark.asyncio
+async def test_can_use_executable_attribute(program: Program) -> None:
+ await program.rpc["test_executable"](
+ ctx=Context(accounts={"program": program.program_id}),
+ )
+ # sleep so we don't get AlreadyProcessed error
+ await asyncio.sleep(10)
+ with raises(ProgramError):
+ await program.rpc["test_executable"](
+ ctx=Context(accounts={"program": program.provider.wallet.public_key}),
+ )
+
+
+@mark.asyncio
+async def test_can_execute_fallback_function(program: Program) -> None:
+ with raises(RPCNoResultException) as excinfo:
+ await invoke(program.program_id, program.provider)
+ assert (
+ "Transaction failed to sanitize accounts offsets correctly"
+ in excinfo.value.args[0]
+ )
+
+
+@mark.asyncio
+async def test_can_fetch_all_accounts_of_a_given_type(
+ program: Program, event_loop
+) -> None:
+ # Initialize the accounts.
+ data1 = Keypair()
+ data2 = Keypair()
+ data3 = Keypair()
+ data4 = Keypair()
+ # Initialize filterable data.
+ filterable1 = Keypair().pubkey()
+ filterable2 = Keypair().pubkey()
+ provider = Provider(
+ program.provider.connection,
+ Wallet(Keypair()),
+ program.provider.opts,
+ )
+ another_program = Program(program.idl, program.program_id, provider)
+ lamports_per_sol = 1000000000
+ tx_res = await program.provider.connection.request_airdrop(
+ another_program.provider.wallet.public_key,
+ lamports_per_sol,
+ )
+ signature = tx_res.value
+ await program.provider.connection.confirm_transaction(signature)
+ # Create all the accounts.
+ tasks = [
+ program.rpc["test_fetch_all"](
+ filterable1,
+ ctx=Context(
+ accounts={
+ "data": data1.pubkey(),
+ "authority": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data1],
+ ),
+ ),
+ program.rpc["test_fetch_all"](
+ filterable1,
+ ctx=Context(
+ accounts={
+ "data": data2.pubkey(),
+ "authority": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data2],
+ ),
+ ),
+ program.rpc["test_fetch_all"](
+ filterable2,
+ ctx=Context(
+ accounts={
+ "data": data3.pubkey(),
+ "authority": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data3],
+ ),
+ ),
+ another_program.rpc["test_fetch_all"](
+ filterable1,
+ ctx=Context(
+ accounts={
+ "data": data4.pubkey(),
+ "authority": another_program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data4],
+ ),
+ ),
+ ]
+ await asyncio.wait([event_loop.create_task(t) for t in tasks])
+ all_accounts = await program.account["DataWithFilter"].all()
+ all_accounts_filtered_by_bytes = await program.account["DataWithFilter"].all(
+ bytes(program.provider.wallet.public_key),
+ )
+ all_accounts_filtered_by_program_filters1 = await program.account[
+ "DataWithFilter"
+ ].all(
+ filters=[
+ MemcmpOpts(offset=8, bytes=str(program.provider.wallet.public_key)),
+ MemcmpOpts(offset=40, bytes=str(filterable1)),
+ ],
+ )
+ all_accounts_filtered_by_program_filters2 = await program.account[
+ "DataWithFilter"
+ ].all(
+ filters=[
+ MemcmpOpts(offset=8, bytes=str(program.provider.wallet.public_key)),
+ MemcmpOpts(offset=40, bytes=str(filterable2)),
+ ],
+ )
+ assert len(all_accounts) == 4
+ assert len(all_accounts_filtered_by_bytes) == 3
+ assert len(all_accounts_filtered_by_program_filters1) == 2
+ assert len(all_accounts_filtered_by_program_filters2) == 1
diff --git a/basics/anchorpy-main/tests/test_misc_core.py b/basics/anchorpy-main/tests/test_misc_core.py
new file mode 100644
index 0000000..cb09d1e
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_misc_core.py
@@ -0,0 +1,686 @@
+"""Mimics anchor/tests/misc/tests/misc.js."""
+from pathlib import Path
+
+from anchorpy import Context, Program
+from anchorpy.error import ProgramError
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from pytest import fixture, mark, raises
+from pytest_asyncio import fixture as async_fixture
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.system_program import TransferParams, transfer
+from solders.sysvar import RENT
+from spl.token.async_client import AsyncToken
+from spl.token.constants import TOKEN_PROGRAM_ID
+
+PATH = Path("anchor/tests/misc/")
+workspace = workspace_fixture(PATH, build_cmd="anchor build --skip-lint")
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ return workspace["misc"]
+
+
+@fixture(scope="module")
+def misc2program(workspace: WorkspaceType) -> Program:
+ return workspace["misc2"]
+
+
+@async_fixture(scope="module")
+async def initialized_keypair(program: Program) -> Keypair:
+ data = Keypair()
+ await program.rpc["initialize"](
+ 1234,
+ 22,
+ ctx=Context(
+ accounts={"data": data.pubkey(), "rent": RENT},
+ signers=[data],
+ pre_instructions=[await program.account["Data"].create_instruction(data)],
+ ),
+ )
+ return data
+
+
+@mark.asyncio
+async def test_can_use_u128_and_i128(
+ program: Program, initialized_keypair: Keypair
+) -> None:
+ data_account = await program.account["Data"].fetch(initialized_keypair.pubkey())
+ assert data_account.udata == 1234
+ assert data_account.idata == 22
+
+
+@async_fixture(scope="module")
+async def keypair_after_test_u16(program: Program) -> Keypair:
+ data = Keypair()
+ await program.rpc["test_u16"](
+ 99,
+ ctx=Context(
+ accounts={"my_account": data.pubkey(), "rent": RENT},
+ signers=[data],
+ pre_instructions=[
+ await program.account["DataU16"].create_instruction(data)
+ ],
+ ),
+ )
+ return data
+
+
+@mark.asyncio
+async def test_can_use_u16(
+ program: Program,
+ keypair_after_test_u16: Keypair,
+) -> None:
+ data_account = await program.account["DataU16"].fetch(
+ keypair_after_test_u16.pubkey(),
+ )
+ assert data_account.data == 99
+
+
+@mark.asyncio
+async def test_can_use_owner_constraint(
+ program: Program, initialized_keypair: Keypair
+) -> None:
+ await program.rpc["test_owner"](
+ ctx=Context(
+ accounts={
+ "data": initialized_keypair.pubkey(),
+ "misc": program.program_id,
+ },
+ ),
+ )
+ with raises(ProgramError):
+ await program.rpc["test_owner"](
+ ctx=Context(
+ accounts={
+ "data": program.provider.wallet.public_key,
+ "misc": program.program_id,
+ },
+ ),
+ )
+
+
+@mark.asyncio
+async def test_can_retrieve_events_when_simulating_transaction(
+ program: Program,
+) -> None:
+ resp = await program.simulate["test_simulate"](44)
+ expected_raw_first_entry = (
+ "Program 3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh invoke [1]"
+ )
+ events = resp.events
+ assert resp.raw[0] == expected_raw_first_entry
+ assert events[0].name == "E1"
+ assert events[0].data.data == 44
+ assert events[1].name == "E2"
+ assert events[1].data.data == 1234
+ assert events[2].name == "E3"
+ assert events[2].data.data == 9
+
+
+@mark.asyncio
+async def test_can_use_i8_in_idl(program: Program) -> None:
+ data = Keypair()
+ await program.rpc["test_i8"](
+ -3,
+ ctx=Context(
+ accounts={"data": data.pubkey(), "rent": RENT},
+ pre_instructions=[await program.account["DataI8"].create_instruction(data)],
+ signers=[data],
+ ),
+ )
+ data_account = await program.account["DataI8"].fetch(data.pubkey())
+ assert data_account.data == -3
+
+
+@async_fixture(scope="module")
+async def data_i16_keypair(program: Program) -> Keypair:
+ data = Keypair()
+ await program.rpc["test_i16"](
+ -2048,
+ ctx=Context(
+ accounts={"data": data.pubkey(), "rent": RENT},
+ pre_instructions=[
+ await program.account["DataI16"].create_instruction(data)
+ ],
+ signers=[data],
+ ),
+ )
+ return data
+
+
+@mark.asyncio
+async def test_can_use_i16_in_idl(program: Program, data_i16_keypair: Keypair) -> None:
+ data_account = await program.account["DataI16"].fetch(data_i16_keypair.pubkey())
+ assert data_account.data == -2048
+
+
+@mark.asyncio
+async def test_fail_to_close_account_when_sending_lamports_to_itself(
+ program: Program,
+ initialized_keypair: Keypair,
+) -> None:
+ with raises(ProgramError) as excinfo:
+ await program.rpc["test_close"](
+ ctx=Context(
+ accounts={
+ "data": initialized_keypair.pubkey(),
+ "sol_dest": initialized_keypair.pubkey(),
+ },
+ ),
+ )
+ assert excinfo.value.code == 2011
+ assert excinfo.value.msg == "A close constraint was violated"
+
+
+@mark.asyncio
+async def test_can_close_account(
+ program: Program,
+ initialized_keypair: Keypair,
+) -> None:
+ open_account = await program.provider.connection.get_account_info(
+ initialized_keypair.pubkey(),
+ )
+ assert open_account.value is not None
+ before_balance_raw = await program.provider.connection.get_account_info(
+ program.provider.wallet.public_key,
+ )
+ before_balance_res = before_balance_raw.value
+ assert before_balance_res is not None
+ before_balance = before_balance_res.lamports
+ await program.rpc["test_close"](
+ ctx=Context(
+ accounts={
+ "data": initialized_keypair.pubkey(),
+ "sol_dest": program.provider.wallet.public_key,
+ },
+ ),
+ )
+ after_balance_raw = await program.provider.connection.get_account_info(
+ program.provider.wallet.public_key,
+ )
+ after_balance_res = after_balance_raw.value
+ assert after_balance_res is not None
+ after_balance = after_balance_res.lamports
+ assert after_balance > before_balance
+ closed_account = await program.provider.connection.get_account_info(
+ initialized_keypair.pubkey(),
+ )
+ assert closed_account.value is None
+
+
+@mark.asyncio
+async def test_can_use_instruction_data_in_accounts_constraints(
+ program: Program,
+) -> None:
+ seed = b"my-seed"
+ my_pda, nonce = Pubkey.find_program_address([seed, bytes(RENT)], program.program_id)
+ await program.rpc["test_instruction_constraint"](
+ nonce,
+ ctx=Context(accounts={"my_pda": my_pda, "my_account": RENT}),
+ )
+
+
+@mark.asyncio
+async def test_can_create_a_pda_with_instruction_data(
+ program: Program,
+) -> None:
+ seed = bytes([1, 2, 3, 4])
+ domain = "my-domain"
+ foo = RENT
+ my_pda, nonce = Pubkey.find_program_address(
+ [b"my-seed", domain.encode(), bytes(foo), seed], program.program_id
+ )
+ await program.rpc["test_pda_init"](
+ domain,
+ seed,
+ nonce,
+ ctx=Context(
+ accounts={
+ "my_pda": my_pda,
+ "my_payer": program.provider.wallet.public_key,
+ "foo": foo,
+ "rent": RENT,
+ "system_program": SYS_PROGRAM_ID,
+ }
+ ),
+ )
+ my_pda_account = await program.account["DataU16"].fetch(my_pda)
+ assert my_pda_account.data == 6
+
+
+@mark.asyncio
+async def test_can_create_a_zero_copy_pda(program: Program) -> None:
+ my_pda, nonce = Pubkey.find_program_address([b"my-seed"], program.program_id)
+ await program.rpc["test_pda_init_zero_copy"](
+ ctx=Context(
+ accounts={
+ "my_pda": my_pda,
+ "my_payer": program.provider.wallet.public_key,
+ "rent": RENT,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ ),
+ )
+ my_pda_account = await program.account["DataZeroCopy"].fetch(my_pda)
+ assert my_pda_account.data == 9
+ assert my_pda_account.bump == nonce
+
+
+@mark.asyncio
+async def test_can_write_to_a_zero_copy_pda(program: Program) -> None:
+ my_pda, bump = Pubkey.find_program_address([b"my-seed"], program.program_id)
+ await program.rpc["test_pda_mut_zero_copy"](
+ ctx=Context(
+ accounts={
+ "my_pda": my_pda,
+ "my_payer": program.provider.wallet.public_key,
+ },
+ )
+ )
+ my_pda_account = await program.account["DataZeroCopy"].fetch(my_pda)
+ assert my_pda_account.data == 1234
+ assert my_pda_account.bump == bump
+
+
+@mark.asyncio
+async def test_can_create_a_token_account_from_seeds_pda(program: Program) -> None:
+ mint, mint_bump = Pubkey.find_program_address([b"my-mint-seed"], program.program_id)
+ my_pda, token_bump = Pubkey.find_program_address(
+ [b"my-token-seed"], program.program_id
+ )
+ await program.rpc["test_token_seeds_init"](
+ ctx=Context(
+ accounts={
+ "my_pda": my_pda,
+ "mint": mint,
+ "authority": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ "rent": RENT,
+ "token_program": TOKEN_PROGRAM_ID,
+ },
+ ),
+ )
+ mint_account = AsyncToken(
+ program.provider.connection,
+ mint,
+ TOKEN_PROGRAM_ID,
+ program.provider.wallet.payer,
+ )
+ account = await mint_account.get_account_info(my_pda)
+ assert account.is_frozen is False
+ assert account.is_initialized is True
+ assert account.amount == 0
+ assert account.owner == program.provider.wallet.public_key
+ assert account.mint == mint
+
+
+@mark.asyncio
+async def test_can_init_random_account(program: Program) -> None:
+ data = Keypair()
+ await program.rpc["test_init"](
+ ctx=Context(
+ accounts={
+ "data": data.pubkey(),
+ "payer": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data],
+ ),
+ )
+ account = await program.account["DataI8"].fetch(data.pubkey())
+ assert account.data == 3
+
+
+@mark.asyncio
+async def test_can_init_random_account_prefunded(program: Program) -> None:
+ data = Keypair()
+ await program.rpc["test_init"](
+ ctx=Context(
+ accounts={
+ "data": data.pubkey(),
+ "payer": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data],
+ pre_instructions=[
+ transfer(
+ TransferParams(
+ from_pubkey=program.provider.wallet.public_key,
+ to_pubkey=data.pubkey(),
+ lamports=4039280,
+ ),
+ ),
+ ],
+ ),
+ )
+ account = await program.account["DataI8"].fetch(data.pubkey())
+ assert account.data == 3
+
+
+@mark.asyncio
+async def test_can_init_random_zero_copy_account(program: Program) -> None:
+ data = Keypair()
+ await program.rpc["test_init_zero_copy"](
+ ctx=Context(
+ accounts={
+ "data": data.pubkey(),
+ "payer": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data],
+ ),
+ )
+ account = await program.account["DataZeroCopy"].fetch(data.pubkey())
+ assert account.data == 10
+ assert account.bump == 2
+
+
+@mark.asyncio
+async def test_can_create_random_mint_account(
+ program: Program,
+) -> None:
+ mint = Keypair()
+ await program.rpc["test_init_mint"](
+ ctx=Context(
+ accounts={
+ "mint": mint.pubkey(),
+ "payer": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[mint],
+ ),
+ )
+ client = AsyncToken(
+ program.provider.connection,
+ mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ program.provider.wallet.payer,
+ )
+ mint_account = await client.get_mint_info()
+ assert mint_account.decimals == 6
+ assert mint_account.mint_authority == program.provider.wallet.public_key
+ assert mint_account.freeze_authority == program.provider.wallet.public_key
+
+
+@async_fixture(scope="module")
+async def prefunded_mint(program: Program) -> Keypair:
+ mint = Keypair()
+ await program.rpc["test_init_mint"](
+ ctx=Context(
+ accounts={
+ "mint": mint.pubkey(),
+ "payer": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[mint],
+ pre_instructions=[
+ transfer(
+ TransferParams(
+ from_pubkey=program.provider.wallet.public_key,
+ to_pubkey=mint.pubkey(),
+ lamports=4039280,
+ ),
+ ),
+ ],
+ ),
+ )
+ return mint
+
+
+@mark.asyncio
+async def test_can_create_random_mint_account_prefunded(
+ program: Program,
+ prefunded_mint: Keypair,
+) -> None:
+ client = AsyncToken(
+ program.provider.connection,
+ prefunded_mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ program.provider.wallet.payer,
+ )
+ mint_account = await client.get_mint_info()
+ assert mint_account.decimals == 6
+ assert mint_account.mint_authority == program.provider.wallet.public_key
+
+
+@mark.asyncio
+async def test_can_create_random_token_account(
+ program: Program,
+ prefunded_mint: Keypair,
+) -> None:
+ token = Keypair()
+ await program.rpc["test_init_token"](
+ ctx=Context(
+ accounts={
+ "token": token.pubkey(),
+ "mint": prefunded_mint.pubkey(),
+ "payer": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[token],
+ ),
+ )
+ client = AsyncToken(
+ program.provider.connection,
+ prefunded_mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ program.provider.wallet.payer,
+ )
+ account = await client.get_account_info(token.pubkey())
+ assert not account.is_frozen
+ assert account.amount == 0
+ assert account.is_initialized
+ assert account.owner == program.provider.wallet.public_key
+ assert account.mint == prefunded_mint.pubkey()
+
+
+@mark.asyncio
+async def test_can_create_random_token_account_with_prefunding(
+ program: Program,
+ prefunded_mint: Keypair,
+) -> None:
+ token = Keypair()
+ await program.rpc["test_init_token"](
+ ctx=Context(
+ accounts={
+ "token": token.pubkey(),
+ "mint": prefunded_mint.pubkey(),
+ "payer": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[token],
+ pre_instructions=[
+ transfer(
+ TransferParams(
+ from_pubkey=program.provider.wallet.public_key,
+ to_pubkey=token.pubkey(),
+ lamports=4039280,
+ ),
+ )
+ ],
+ ),
+ )
+ client = AsyncToken(
+ program.provider.connection,
+ prefunded_mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ program.provider.wallet.payer,
+ )
+ account = await client.get_account_info(token.pubkey())
+ assert not account.is_frozen
+ assert account.amount == 0
+ assert account.is_initialized
+ assert account.owner == program.provider.wallet.public_key
+ assert account.mint == prefunded_mint.pubkey()
+
+
+@mark.asyncio
+async def test_can_create_random_token_account_with_prefunding_under_rent_exemption(
+ program: Program,
+ prefunded_mint: Keypair,
+) -> None:
+ token = Keypair()
+ await program.rpc["test_init_token"](
+ ctx=Context(
+ accounts={
+ "token": token.pubkey(),
+ "mint": prefunded_mint.pubkey(),
+ "payer": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[token],
+ pre_instructions=[
+ transfer(
+ TransferParams(
+ from_pubkey=program.provider.wallet.public_key,
+ to_pubkey=token.pubkey(),
+ lamports=1,
+ ),
+ )
+ ],
+ ),
+ )
+ client = AsyncToken(
+ program.provider.connection,
+ prefunded_mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ program.provider.wallet.payer,
+ )
+ account = await client.get_account_info(token.pubkey())
+ assert not account.is_frozen
+ assert account.amount == 0
+ assert account.is_initialized
+ assert account.owner == program.provider.wallet.public_key
+ assert account.mint == prefunded_mint.pubkey()
+
+
+@mark.asyncio
+async def test_init_multiple_accounts_via_composite_payer(program: Program) -> None:
+ data1 = Keypair()
+ data2 = Keypair()
+ await program.rpc["test_composite_payer"](
+ ctx=Context(
+ accounts={
+ "composite": {
+ "data": data1.pubkey(),
+ "payer": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ "data": data2.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data1, data2],
+ )
+ )
+ account1 = await program.account["DataI8"].fetch(data1.pubkey())
+ assert account1.data == 1
+
+ account2 = await program.account["Data"].fetch(data2.pubkey())
+ assert account2.udata == 2
+ assert account2.idata == 3
+
+
+@mark.asyncio
+async def test_can_create_associated_token_account(program: Program) -> None:
+ # TODO
+ pass
+
+
+@mark.asyncio
+async def test_can_validate_associated_token_constraints(program: Program) -> None:
+ # TODO
+ pass
+
+
+@mark.asyncio
+async def test_can_use_pdas_with_empty_seeds(program: Program) -> None:
+ pda, bump = Pubkey.find_program_address([], program.program_id)
+ await program.rpc["test_init_with_empty_seeds"](
+ ctx=Context(
+ accounts={
+ "pda": pda,
+ "authority": program.provider.wallet.public_key,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ ),
+ )
+ await program.rpc["test_empty_seeds_constraint"](
+ ctx=Context(
+ accounts={
+ "pda": pda,
+ },
+ ),
+ )
+ pda2, _ = Pubkey.find_program_address(
+ [b"non-empty"],
+ program.program_id,
+ )
+ with raises(ProgramError) as excinfo:
+ await program.rpc["test_empty_seeds_constraint"](
+ ctx=Context(
+ accounts={
+ "pda": pda2,
+ },
+ ),
+ )
+ assert excinfo.value.code == 2006
+
+
+@async_fixture(scope="module")
+async def if_needed_acc(program: Program) -> Keypair:
+ keypair = Keypair()
+ await program.rpc["test_init_if_needed"](
+ 1,
+ ctx=Context(
+ accounts={
+ "data": keypair.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "payer": program.provider.wallet.public_key,
+ },
+ signers=[keypair],
+ ),
+ )
+ return keypair
+
+
+@mark.asyncio
+async def test_can_init_if_needed_a_new_account(
+ program: Program,
+ if_needed_acc: Keypair,
+) -> None:
+ account = await program.account["DataU16"].fetch(if_needed_acc.pubkey())
+ assert account.data == 1
+
+
+@mark.asyncio
+async def test_can_init_if_needed_a_previously_created_account(
+ program: Program,
+ if_needed_acc: Keypair,
+) -> None:
+ await program.rpc["test_init_if_needed"](
+ 3,
+ ctx=Context(
+ accounts={
+ "data": if_needed_acc.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "payer": program.provider.wallet.public_key,
+ },
+ signers=[if_needed_acc],
+ ),
+ )
+ account = await program.account["DataU16"].fetch(if_needed_acc.pubkey())
+ assert account.data == 3
diff --git a/basics/anchorpy-main/tests/test_misc_core_bankrun.py b/basics/anchorpy-main/tests/test_misc_core_bankrun.py
new file mode 100644
index 0000000..b86d927
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_misc_core_bankrun.py
@@ -0,0 +1,938 @@
+"""Mimics anchor/tests/misc/tests/misc.js."""
+from pathlib import Path
+from typing import Any, AsyncGenerator, Optional
+
+from anchorpy import Context, Program
+from anchorpy.error import ProgramError
+from anchorpy.program.context import EMPTY_CONTEXT
+from anchorpy.program.core import _parse_idl_errors
+from anchorpy.program.event import EventParser
+from anchorpy.program.namespace.account import AccountClient
+from anchorpy.program.namespace.simulate import SimulateResponse
+from anchorpy.pytest_plugin import bankrun_fixture
+from anchorpy.workspace import WorkspaceType, close_workspace, create_workspace
+from pytest import fixture, mark, raises
+from pytest_asyncio import fixture as async_fixture
+from solana.rpc.core import RPCException
+from solders.account import Account
+from solders.bankrun import BanksClientError, ProgramTestContext
+from solders.instruction import Instruction
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.rpc.responses import GetAccountInfoResp, RpcResponseContext
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.system_program import (
+ CreateAccountParams,
+ TransferParams,
+ create_account,
+ transfer,
+)
+from solders.sysvar import RENT
+from spl.token.async_client import AsyncToken
+from spl.token.constants import TOKEN_PROGRAM_ID
+
+PATH = Path("anchor/tests/misc/")
+bankrun = bankrun_fixture(PATH, build_cmd="anchor build --skip-lint")
+
+
+@async_fixture(scope="module")
+async def workspace(bankrun: ProgramTestContext) -> AsyncGenerator[WorkspaceType, None]:
+ ws = create_workspace(PATH)
+ yield ws
+ await close_workspace(ws)
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ return workspace["misc"]
+
+
+@fixture(scope="module")
+def misc2program(workspace: WorkspaceType) -> Program:
+ return workspace["misc2"]
+
+
+async def bankrun_rpc(
+ prog: Program, name: str, args: list, ctx: Context, bankrun: ProgramTestContext
+) -> None:
+ recent_blockhash = (await bankrun.banks_client.get_latest_blockhash())[0]
+ tx = prog.transaction[name](
+ *args, payer=bankrun.payer, blockhash=recent_blockhash, ctx=ctx
+ )
+ await bankrun.banks_client.process_transaction(tx)
+
+
+def as_account_info_resp(acc: Optional[Account]) -> GetAccountInfoResp:
+ return GetAccountInfoResp(acc, RpcResponseContext(0))
+
+
+async def bankrun_create_instruction(
+ acc: AccountClient, signer: Keypair, program_id: Pubkey, bankrun: ProgramTestContext
+) -> Instruction:
+ rent = await bankrun.banks_client.get_rent()
+ space = acc._size
+ mbre = rent.minimum_balance(space)
+ return create_account(
+ CreateAccountParams(
+ from_pubkey=bankrun.payer.pubkey(),
+ to_pubkey=signer.pubkey(),
+ space=space,
+ lamports=mbre,
+ owner=program_id,
+ )
+ )
+
+
+async def bankrun_fetch(
+ acc: AccountClient, address: Pubkey, bankrun: ProgramTestContext
+) -> Any:
+ raw = await bankrun.banks_client.get_account(address)
+ assert raw is not None
+ return acc.coder.accounts.decode(raw.data)
+
+
+async def bankrun_simulate(
+ prog: Program, name: str, args: list, ctx: Context, bankrun: ProgramTestContext
+) -> SimulateResponse:
+ blockhash = (await bankrun.banks_client.get_latest_blockhash())[0]
+ tx = prog.transaction[name](
+ *args, payer=bankrun.payer, blockhash=blockhash, ctx=ctx
+ )
+ resp = await bankrun.banks_client.simulate_transaction(tx)
+ resp_err = resp.result
+ meta = resp.meta
+ logs = [] if meta is None else meta.log_messages
+ idl_errors = _parse_idl_errors(prog.idl)
+ if resp_err is None:
+ events = []
+ if prog.idl.events is not None:
+ parser = EventParser(prog.program_id, prog.coder)
+ parser.parse_logs(logs, lambda evt: events.append(evt))
+ return SimulateResponse(events, logs)
+ else:
+ translated_err = ProgramError.parse_tx_error(
+ resp_err, idl_errors, prog.program_id, logs
+ )
+ if translated_err is not None:
+ raise translated_err
+ raise RPCException(resp_err)
+
+
+@async_fixture(scope="module")
+async def initialized_keypair(program: Program, bankrun: ProgramTestContext) -> Keypair:
+ data = Keypair()
+ await bankrun_rpc(
+ program,
+ "initialize",
+ [
+ 1234,
+ 22,
+ ],
+ ctx=Context(
+ accounts={"data": data.pubkey(), "rent": RENT},
+ signers=[data],
+ pre_instructions=[
+ await bankrun_create_instruction(
+ program.account["Data"], data, program.program_id, bankrun
+ )
+ ],
+ ),
+ bankrun=bankrun,
+ )
+ return data
+
+
+@mark.asyncio
+async def test_can_use_u128_and_i128(
+ program: Program, initialized_keypair: Keypair, bankrun: ProgramTestContext
+) -> None:
+ data_account = await bankrun_fetch(
+ program.account["Data"], initialized_keypair.pubkey(), bankrun
+ )
+ assert data_account.udata == 1234
+ assert data_account.idata == 22
+
+
+@async_fixture(scope="module")
+async def keypair_after_test_u16(
+ program: Program, bankrun: ProgramTestContext
+) -> Keypair:
+ data = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_u16",
+ [99],
+ ctx=Context(
+ accounts={"my_account": data.pubkey(), "rent": RENT},
+ signers=[data],
+ pre_instructions=[
+ await bankrun_create_instruction(
+ program.account["DataU16"], data, program.program_id, bankrun
+ )
+ ],
+ ),
+ bankrun=bankrun,
+ )
+ return data
+
+
+@mark.asyncio
+async def test_can_use_u16(
+ program: Program,
+ keypair_after_test_u16: Keypair,
+ bankrun: ProgramTestContext,
+) -> None:
+ data_account = await bankrun_fetch(
+ program.account["DataU16"], keypair_after_test_u16.pubkey(), bankrun
+ )
+ assert data_account.data == 99
+
+
+@mark.asyncio
+async def test_can_use_owner_constraint(
+ program: Program, initialized_keypair: Keypair, bankrun: ProgramTestContext
+) -> None:
+ await bankrun_rpc(
+ program,
+ "test_owner",
+ [],
+ ctx=Context(
+ accounts={
+ "data": initialized_keypair.pubkey(),
+ "misc": program.program_id,
+ },
+ ),
+ bankrun=bankrun,
+ )
+ with raises(BanksClientError):
+ await bankrun_rpc(
+ program,
+ "test_owner",
+ [],
+ ctx=Context(
+ accounts={
+ "data": bankrun.payer.pubkey(),
+ "misc": program.program_id,
+ },
+ ),
+ bankrun=bankrun,
+ )
+
+
+@mark.asyncio
+async def test_can_retrieve_events_when_simulating_transaction(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ resp = await bankrun_simulate(
+ program, "test_simulate", [44], ctx=EMPTY_CONTEXT, bankrun=bankrun
+ )
+ expected_raw_first_entry = (
+ "Program 3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh invoke [1]"
+ )
+ events = resp.events
+ assert resp.raw[0] == expected_raw_first_entry
+ assert events[0].name == "E1"
+ assert events[0].data.data == 44
+ assert events[1].name == "E2"
+ assert events[1].data.data == 1234
+ assert events[2].name == "E3"
+ assert events[2].data.data == 9
+
+
+@mark.asyncio
+async def test_can_use_i8_in_idl(program: Program, bankrun: ProgramTestContext) -> None:
+ data = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_i8",
+ [-3],
+ ctx=Context(
+ accounts={"data": data.pubkey(), "rent": RENT},
+ pre_instructions=[
+ await bankrun_create_instruction(
+ program.account["DataI8"], data, program.program_id, bankrun
+ )
+ ],
+ signers=[data],
+ ),
+ bankrun=bankrun,
+ )
+ data_account = await bankrun_fetch(
+ program.account["DataI8"], data.pubkey(), bankrun
+ )
+ assert data_account.data == -3
+
+
+@async_fixture(scope="module")
+async def data_i16_keypair(program: Program, bankrun: ProgramTestContext) -> Keypair:
+ data = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_i16",
+ [-2048],
+ ctx=Context(
+ accounts={"data": data.pubkey(), "rent": RENT},
+ pre_instructions=[
+ await bankrun_create_instruction(
+ program.account["DataI16"], data, program.program_id, bankrun
+ )
+ ],
+ signers=[data],
+ ),
+ bankrun=bankrun,
+ )
+ return data
+
+
+@mark.asyncio
+async def test_can_use_i16_in_idl(
+ program: Program, data_i16_keypair: Keypair, bankrun: ProgramTestContext
+) -> None:
+ data_account = await bankrun_fetch(
+ program.account["DataI16"], data_i16_keypair.pubkey(), bankrun
+ )
+ assert data_account.data == -2048
+
+
+@mark.asyncio
+async def test_fail_to_close_account_when_sending_lamports_to_itself(
+ program: Program,
+ initialized_keypair: Keypair,
+ bankrun: ProgramTestContext,
+) -> None:
+ with raises(BanksClientError) as excinfo:
+ await bankrun_rpc(
+ program,
+ "test_close",
+ [],
+ ctx=Context(
+ accounts={
+ "data": initialized_keypair.pubkey(),
+ "sol_dest": initialized_keypair.pubkey(),
+ },
+ ),
+ bankrun=bankrun,
+ )
+ assert "0x7db" in excinfo.value.args[0]
+
+
+@mark.asyncio
+async def test_can_close_account(
+ program: Program,
+ initialized_keypair: Keypair,
+ bankrun: ProgramTestContext,
+) -> None:
+ client = bankrun.banks_client
+ open_account = await client.get_account(initialized_keypair.pubkey())
+ assert open_account is not None
+ before_balance_res = await client.get_account(
+ bankrun.payer.pubkey(),
+ )
+ assert before_balance_res is not None
+ before_balance = before_balance_res.lamports
+ await bankrun_rpc(
+ program,
+ "test_close",
+ [],
+ ctx=Context(
+ accounts={
+ "data": initialized_keypair.pubkey(),
+ "sol_dest": bankrun.payer.pubkey(),
+ },
+ ),
+ bankrun=bankrun,
+ )
+ after_balance_res = await client.get_account(
+ bankrun.payer.pubkey(),
+ )
+ assert after_balance_res is not None
+ after_balance = after_balance_res.lamports
+ assert after_balance > before_balance
+ closed_account = await client.get_account(
+ initialized_keypair.pubkey(),
+ )
+ assert closed_account is None
+
+
+@mark.asyncio
+async def test_can_use_instruction_data_in_accounts_constraints(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ seed = b"my-seed"
+ my_pda, nonce = Pubkey.find_program_address([seed, bytes(RENT)], program.program_id)
+ await bankrun_rpc(
+ program,
+ "test_instruction_constraint",
+ [nonce],
+ ctx=Context(accounts={"my_pda": my_pda, "my_account": RENT}),
+ bankrun=bankrun,
+ )
+
+
+@mark.asyncio
+async def test_can_create_a_pda_with_instruction_data(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ seed = bytes([1, 2, 3, 4])
+ domain = "my-domain"
+ foo = RENT
+ my_pda, nonce = Pubkey.find_program_address(
+ [b"my-seed", domain.encode(), bytes(foo), seed], program.program_id
+ )
+ await bankrun_rpc(
+ program,
+ "test_pda_init",
+ [domain, seed, nonce],
+ ctx=Context(
+ accounts={
+ "my_pda": my_pda,
+ "my_payer": bankrun.payer.pubkey(),
+ "foo": foo,
+ "rent": RENT,
+ "system_program": SYS_PROGRAM_ID,
+ }
+ ),
+ bankrun=bankrun,
+ )
+ my_pda_account = await bankrun_fetch(program.account["DataU16"], my_pda, bankrun)
+ assert my_pda_account.data == 6
+
+
+@mark.asyncio
+async def test_can_create_a_zero_copy_pda(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ my_pda, nonce = Pubkey.find_program_address([b"my-seed"], program.program_id)
+ await bankrun_rpc(
+ program,
+ "test_pda_init_zero_copy",
+ [],
+ ctx=Context(
+ accounts={
+ "my_pda": my_pda,
+ "my_payer": bankrun.payer.pubkey(),
+ "rent": RENT,
+ "system_program": SYS_PROGRAM_ID,
+ },
+ ),
+ bankrun=bankrun,
+ )
+ my_pda_account = await bankrun_fetch(
+ program.account["DataZeroCopy"], my_pda, bankrun
+ )
+ assert my_pda_account.data == 9
+ assert my_pda_account.bump == nonce
+
+
+@mark.asyncio
+async def test_can_write_to_a_zero_copy_pda(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ my_pda, bump = Pubkey.find_program_address([b"my-seed"], program.program_id)
+ await bankrun_rpc(
+ program,
+ "test_pda_mut_zero_copy",
+ [],
+ ctx=Context(
+ accounts={
+ "my_pda": my_pda,
+ "my_payer": bankrun.payer.pubkey(),
+ },
+ ),
+ bankrun=bankrun,
+ )
+ my_pda_account = await bankrun_fetch(
+ program.account["DataZeroCopy"], my_pda, bankrun
+ )
+ assert my_pda_account.data == 1234
+ assert my_pda_account.bump == bump
+
+
+@mark.asyncio
+async def test_can_create_a_token_account_from_seeds_pda(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ mint, mint_bump = Pubkey.find_program_address([b"my-mint-seed"], program.program_id)
+ my_pda, token_bump = Pubkey.find_program_address(
+ [b"my-token-seed"], program.program_id
+ )
+ await bankrun_rpc(
+ program,
+ "test_token_seeds_init",
+ [],
+ ctx=Context(
+ accounts={
+ "my_pda": my_pda,
+ "mint": mint,
+ "authority": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "rent": RENT,
+ "token_program": TOKEN_PROGRAM_ID,
+ },
+ ),
+ bankrun=bankrun,
+ )
+ mint_account = AsyncToken(
+ program.provider.connection, mint, TOKEN_PROGRAM_ID, bankrun.payer
+ )
+ account_raw = await bankrun.banks_client.get_account(my_pda)
+ as_acc_info = as_account_info_resp(account_raw)
+ account = mint_account._create_account_info(as_acc_info)
+ assert account.is_frozen is False
+ assert account.is_initialized is True
+ assert account.amount == 0
+ assert account.owner == bankrun.payer.pubkey()
+ assert account.mint == mint
+
+
+@mark.asyncio
+async def test_can_init_random_account(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ data = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_init",
+ [],
+ ctx=Context(
+ accounts={
+ "data": data.pubkey(),
+ "payer": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data],
+ ),
+ bankrun=bankrun,
+ )
+ account = await bankrun_fetch(program.account["DataI8"], data.pubkey(), bankrun)
+ assert account.data == 3
+
+
+@mark.asyncio
+async def test_can_init_random_account_prefunded(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ data = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_init",
+ [],
+ ctx=Context(
+ accounts={
+ "data": data.pubkey(),
+ "payer": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data],
+ pre_instructions=[
+ transfer(
+ TransferParams(
+ from_pubkey=bankrun.payer.pubkey(),
+ to_pubkey=data.pubkey(),
+ lamports=4039280,
+ ),
+ ),
+ ],
+ ),
+ bankrun=bankrun,
+ )
+ account = await bankrun_fetch(program.account["DataI8"], data.pubkey(), bankrun)
+ assert account.data == 3
+
+
+@mark.asyncio
+async def test_can_init_random_zero_copy_account(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ data = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_init_zero_copy",
+ [],
+ ctx=Context(
+ accounts={
+ "data": data.pubkey(),
+ "payer": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data],
+ ),
+ bankrun=bankrun,
+ )
+ account = await bankrun_fetch(
+ program.account["DataZeroCopy"], data.pubkey(), bankrun
+ )
+ assert account.data == 10
+ assert account.bump == 2
+
+
+@mark.asyncio
+async def test_can_create_random_mint_account(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ mint = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_init_mint",
+ [],
+ ctx=Context(
+ accounts={
+ "mint": mint.pubkey(),
+ "payer": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[mint],
+ ),
+ bankrun=bankrun,
+ )
+ client = AsyncToken(
+ program.provider.connection,
+ mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ bankrun.payer,
+ )
+ mint_acc_raw = await bankrun.banks_client.get_account(client.pubkey)
+ mint_account = client._create_mint_info(as_account_info_resp(mint_acc_raw))
+ assert mint_account.decimals == 6
+ assert mint_account.mint_authority == bankrun.payer.pubkey()
+ assert mint_account.freeze_authority == bankrun.payer.pubkey()
+
+
+@async_fixture(scope="module")
+async def prefunded_mint(program: Program, bankrun: ProgramTestContext) -> Keypair:
+ mint = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_init_mint",
+ [],
+ ctx=Context(
+ accounts={
+ "mint": mint.pubkey(),
+ "payer": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[mint],
+ pre_instructions=[
+ transfer(
+ TransferParams(
+ from_pubkey=bankrun.payer.pubkey(),
+ to_pubkey=mint.pubkey(),
+ lamports=4039280,
+ ),
+ ),
+ ],
+ ),
+ bankrun=bankrun,
+ )
+ return mint
+
+
+@mark.asyncio
+async def test_can_create_random_mint_account_prefunded(
+ program: Program,
+ prefunded_mint: Keypair,
+ bankrun: ProgramTestContext,
+) -> None:
+ client = AsyncToken(
+ program.provider.connection,
+ prefunded_mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ bankrun.payer,
+ )
+ mint_acc_raw = await bankrun.banks_client.get_account(client.pubkey)
+ mint_account = client._create_mint_info(as_account_info_resp(mint_acc_raw))
+ assert mint_account.decimals == 6
+ assert mint_account.mint_authority == bankrun.payer.pubkey()
+
+
+@mark.asyncio
+async def test_can_create_random_token_account(
+ program: Program,
+ prefunded_mint: Keypair,
+ bankrun: ProgramTestContext,
+) -> None:
+ token = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_init_token",
+ [],
+ ctx=Context(
+ accounts={
+ "token": token.pubkey(),
+ "mint": prefunded_mint.pubkey(),
+ "payer": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[token],
+ ),
+ bankrun=bankrun,
+ )
+ client = AsyncToken(
+ program.provider.connection,
+ prefunded_mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ bankrun.payer,
+ )
+ account_raw = await bankrun.banks_client.get_account(token.pubkey())
+ account = client._create_account_info(as_account_info_resp(account_raw))
+ assert not account.is_frozen
+ assert account.amount == 0
+ assert account.is_initialized
+ assert account.owner == bankrun.payer.pubkey()
+ assert account.mint == prefunded_mint.pubkey()
+
+
+@mark.asyncio
+async def test_can_create_random_token_account_with_prefunding(
+ program: Program,
+ prefunded_mint: Keypair,
+ bankrun: ProgramTestContext,
+) -> None:
+ token = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_init_token",
+ [],
+ ctx=Context(
+ accounts={
+ "token": token.pubkey(),
+ "mint": prefunded_mint.pubkey(),
+ "payer": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[token],
+ pre_instructions=[
+ transfer(
+ TransferParams(
+ from_pubkey=bankrun.payer.pubkey(),
+ to_pubkey=token.pubkey(),
+ lamports=4039280,
+ ),
+ )
+ ],
+ ),
+ bankrun=bankrun,
+ )
+ client = AsyncToken(
+ program.provider.connection,
+ prefunded_mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ bankrun.payer,
+ )
+ account_raw = await bankrun.banks_client.get_account(token.pubkey())
+ account = client._create_account_info(as_account_info_resp(account_raw))
+ assert not account.is_frozen
+ assert account.amount == 0
+ assert account.is_initialized
+ assert account.owner == bankrun.payer.pubkey()
+ assert account.mint == prefunded_mint.pubkey()
+
+
+@mark.asyncio
+async def test_can_create_random_token_account_with_prefunding_under_rent_exemption(
+ program: Program,
+ prefunded_mint: Keypair,
+ bankrun: ProgramTestContext,
+) -> None:
+ token = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_init_token",
+ [],
+ ctx=Context(
+ accounts={
+ "token": token.pubkey(),
+ "mint": prefunded_mint.pubkey(),
+ "payer": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "token_program": TOKEN_PROGRAM_ID,
+ "rent": RENT,
+ },
+ signers=[token],
+ pre_instructions=[
+ transfer(
+ TransferParams(
+ from_pubkey=bankrun.payer.pubkey(),
+ to_pubkey=token.pubkey(),
+ lamports=1,
+ ),
+ )
+ ],
+ ),
+ bankrun=bankrun,
+ )
+ client = AsyncToken(
+ program.provider.connection,
+ prefunded_mint.pubkey(),
+ TOKEN_PROGRAM_ID,
+ bankrun.payer,
+ )
+ account_raw = await bankrun.banks_client.get_account(token.pubkey())
+ account = client._create_account_info(as_account_info_resp(account_raw))
+ assert not account.is_frozen
+ assert account.amount == 0
+ assert account.is_initialized
+ assert account.owner == bankrun.payer.pubkey()
+ assert account.mint == prefunded_mint.pubkey()
+
+
+@mark.asyncio
+async def test_init_multiple_accounts_via_composite_payer(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ data1 = Keypair()
+ data2 = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_composite_payer",
+ [],
+ ctx=Context(
+ accounts={
+ "composite": {
+ "data": data1.pubkey(),
+ "payer": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ },
+ "data": data2.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ },
+ signers=[data1, data2],
+ ),
+ bankrun=bankrun,
+ )
+ account1 = await bankrun_fetch(program.account["DataI8"], data1.pubkey(), bankrun)
+ assert account1.data == 1
+
+ account2 = await bankrun_fetch(program.account["Data"], data2.pubkey(), bankrun)
+ assert account2.udata == 2
+ assert account2.idata == 3
+
+
+@mark.asyncio
+async def test_can_create_associated_token_account(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ # TODO
+ pass
+
+
+@mark.asyncio
+async def test_can_validate_associated_token_constraints(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ # TODO
+ pass
+
+
+@mark.asyncio
+async def test_can_use_pdas_with_empty_seeds(
+ program: Program, bankrun: ProgramTestContext
+) -> None:
+ pda, bump = Pubkey.find_program_address([], program.program_id)
+ await bankrun_rpc(
+ program,
+ "test_init_with_empty_seeds",
+ [],
+ ctx=Context(
+ accounts={
+ "pda": pda,
+ "authority": bankrun.payer.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ },
+ ),
+ bankrun=bankrun,
+ )
+ await bankrun_rpc(
+ program,
+ "test_empty_seeds_constraint",
+ [],
+ ctx=Context(
+ accounts={
+ "pda": pda,
+ },
+ ),
+ bankrun=bankrun,
+ )
+ pda2, _ = Pubkey.find_program_address(
+ [b"non-empty"],
+ program.program_id,
+ )
+ with raises(BanksClientError) as excinfo:
+ await bankrun_rpc(
+ program,
+ "test_empty_seeds_constraint",
+ [],
+ ctx=Context(
+ accounts={
+ "pda": pda2,
+ },
+ ),
+ bankrun=bankrun,
+ )
+ assert "0x7d6" in excinfo.value.args[0]
+
+
+@async_fixture(scope="module")
+async def if_needed_acc(program: Program, bankrun: ProgramTestContext) -> Keypair:
+ keypair = Keypair()
+ await bankrun_rpc(
+ program,
+ "test_init_if_needed",
+ [1],
+ ctx=Context(
+ accounts={
+ "data": keypair.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "payer": bankrun.payer.pubkey(),
+ },
+ signers=[keypair],
+ ),
+ bankrun=bankrun,
+ )
+ return keypair
+
+
+@mark.asyncio
+async def test_can_init_if_needed_a_new_account(
+ program: Program,
+ if_needed_acc: Keypair,
+ bankrun: ProgramTestContext,
+) -> None:
+ account = await bankrun_fetch(
+ program.account["DataU16"], if_needed_acc.pubkey(), bankrun
+ )
+ assert account.data == 1
+
+
+@mark.asyncio
+async def test_can_init_if_needed_a_previously_created_account(
+ program: Program,
+ if_needed_acc: Keypair,
+ bankrun: ProgramTestContext,
+) -> None:
+ await bankrun_rpc(
+ program,
+ "test_init_if_needed",
+ [3],
+ ctx=Context(
+ accounts={
+ "data": if_needed_acc.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ "payer": bankrun.payer.pubkey(),
+ },
+ signers=[if_needed_acc],
+ ),
+ bankrun=bankrun,
+ )
+ account = await bankrun_fetch(
+ program.account["DataU16"], if_needed_acc.pubkey(), bankrun
+ )
+ assert account.data == 3
diff --git a/basics/anchorpy-main/tests/test_multisig.py b/basics/anchorpy-main/tests/test_multisig.py
new file mode 100644
index 0000000..696c417
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_multisig.py
@@ -0,0 +1,192 @@
+"""Mimics anchor/tests/multisig."""
+from anchorpy import Context, Program, Provider
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from pytest import fixture, mark
+from pytest_asyncio import fixture as async_fixture
+from solders.instruction import AccountMeta
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.sysvar import RENT
+
+CreatedMultisig = tuple[Keypair, int, list[Pubkey], int, Pubkey, Keypair, Keypair]
+CreatedTransaction = tuple[Keypair, list[dict], bytes, Keypair, Pubkey, list[Pubkey]]
+
+workspace = workspace_fixture(
+ "anchor/tests/multisig/", build_cmd="anchor build --skip-lint"
+)
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ """Create a Program instance."""
+ return workspace["multisig"]
+
+
+@fixture(scope="module")
+def provider(program: Program) -> Provider:
+ """Get a Provider instance."""
+ return program.provider
+
+
+@async_fixture(scope="module")
+async def created_multisig(program: Program) -> CreatedMultisig:
+ """Run the create_multisig RPC function."""
+ multisig = Keypair()
+ multisig_signer, nonce = Pubkey.find_program_address(
+ [bytes(multisig.pubkey())], program.program_id
+ )
+ multisig_size = 200
+ owner_a, owner_b, owner_c = Keypair(), Keypair(), Keypair()
+ owners = [owner_a.pubkey(), owner_b.pubkey(), owner_c.pubkey()]
+ threshold = 2
+ await program.rpc["create_multisig"](
+ owners,
+ threshold,
+ nonce,
+ ctx=Context(
+ accounts={
+ "multisig": multisig.pubkey(),
+ "rent": RENT,
+ },
+ pre_instructions=[
+ await program.account["Multisig"].create_instruction(
+ multisig, multisig_size
+ ),
+ ],
+ signers=[multisig],
+ ),
+ )
+ return multisig, nonce, owners, threshold, multisig_signer, owner_a, owner_b
+
+
+@mark.asyncio
+async def test_created_multisig(
+ created_multisig: CreatedMultisig,
+ program: Program,
+) -> None:
+ multisig, nonce, owners, threshold = created_multisig[:4]
+ multisig_account = await program.account["Multisig"].fetch(multisig.pubkey())
+ assert multisig_account.nonce == nonce
+ assert multisig_account.threshold == threshold
+ assert multisig_account.owners == owners
+
+
+@async_fixture(scope="module")
+async def created_transaction(
+ program: Program,
+ created_multisig: CreatedMultisig,
+) -> CreatedTransaction:
+ owner_d = Keypair()
+ multisig, _, owners, _, multisig_signer, owner_a, _ = created_multisig
+ accounts = [
+ program.type["TransactionAccount"](
+ pubkey=multisig.pubkey(),
+ is_writable=True,
+ is_signer=False,
+ ),
+ program.type["TransactionAccount"](
+ pubkey=multisig_signer,
+ is_writable=False,
+ is_signer=True,
+ ),
+ ]
+ new_owners = [*owners[:2], owner_d.pubkey()]
+ data = program.coder.instruction.encode("set_owners", {"owners": new_owners})
+ transaction = Keypair()
+ tx_size = 1000
+ await program.rpc["create_transaction"](
+ program.program_id,
+ accounts,
+ data,
+ ctx=Context(
+ accounts={
+ "multisig": multisig.pubkey(),
+ "transaction": transaction.pubkey(),
+ "proposer": owner_a.pubkey(),
+ "rent": RENT,
+ },
+ pre_instructions=[
+ await program.account["Transaction"].create_instruction(
+ transaction,
+ tx_size,
+ ),
+ ],
+ signers=[transaction, owner_a],
+ ),
+ )
+ return transaction, accounts, data, multisig, multisig_signer, new_owners
+
+
+@mark.asyncio
+async def test_created_transaction(
+ created_transaction: CreatedTransaction,
+ program: Program,
+) -> None:
+ transaction, accounts, data, multisig, _, _ = created_transaction
+ tx_account = await program.account["Transaction"].fetch(transaction.pubkey())
+ assert tx_account.program_id == program.program_id
+ assert tx_account.accounts == accounts
+ assert tx_account.data == data
+ assert tx_account.multisig == multisig.pubkey()
+ assert tx_account.did_execute is False
+
+
+@async_fixture(scope="module")
+async def executed_transaction(
+ program: Program,
+ created_transaction: CreatedTransaction,
+ created_multisig: CreatedMultisig,
+) -> None:
+ transaction, _, _, multisig, multisig_signer, _ = created_transaction
+ owner_b = created_multisig[6]
+ await program.rpc["approve"](
+ ctx=Context(
+ accounts={
+ "multisig": multisig.pubkey(),
+ "transaction": transaction.pubkey(),
+ "owner": owner_b.pubkey(),
+ },
+ signers=[owner_b],
+ ),
+ )
+ remaining_accounts_raw = program.instruction["set_owners"].accounts(
+ {"multisig": multisig.pubkey(), "multisig_signer": multisig_signer}
+ )
+ with_corrected_signer = []
+ for meta in remaining_accounts_raw:
+ to_append = (
+ AccountMeta(
+ pubkey=meta.pubkey, is_signer=False, is_writable=meta.is_writable
+ )
+ if meta.pubkey == multisig_signer
+ else meta
+ )
+ with_corrected_signer.append(to_append)
+ remaining_accounts = with_corrected_signer + [
+ AccountMeta(pubkey=program.program_id, is_signer=False, is_writable=False)
+ ]
+ ctx = Context(
+ accounts={
+ "multisig": multisig.pubkey(),
+ "multisig_signer": multisig_signer,
+ "transaction": transaction.pubkey(),
+ },
+ remaining_accounts=remaining_accounts,
+ )
+ await program.rpc["execute_transaction"](ctx=ctx)
+
+
+@mark.asyncio
+async def test_executed_transaction(
+ created_multisig: CreatedMultisig,
+ created_transaction: CreatedTransaction,
+ executed_transaction: None,
+ program: Program,
+) -> None:
+ multisig, nonce, _, threshold = created_multisig[:4]
+ new_owners = created_transaction[5]
+ multisig_account = await program.account["Multisig"].fetch(multisig.pubkey())
+ assert multisig_account.nonce == nonce
+ assert multisig_account.threshold == threshold
+ assert multisig_account.owners == new_owners
diff --git a/basics/anchorpy-main/tests/test_pyth.py b/basics/anchorpy-main/tests/test_pyth.py
new file mode 100644
index 0000000..ad5ef28
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_pyth.py
@@ -0,0 +1,135 @@
+"""Mimics anchor/tests/misc/tests/misc.js."""
+from dataclasses import dataclass
+
+from anchorpy import Context, Program
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from construct import Int32sl, Int64ul
+from pytest import fixture, mark
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.system_program import (
+ CreateAccountParams,
+ create_account,
+)
+
+workspace = workspace_fixture(
+ "anchor/tests/pyth/", build_cmd="anchor build --skip-lint"
+)
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ return workspace["pyth"]
+
+
+async def create_price_feed(
+ oracle_program: Program,
+ init_price: int,
+ expo: int,
+) -> Pubkey:
+ conf = int((init_price / 10) * 10**-expo)
+ space = 3312
+ mbre_resp = (
+ await oracle_program.provider.connection.get_minimum_balance_for_rent_exemption(
+ space,
+ )
+ )
+ collateral_token_feed = Keypair()
+ await oracle_program.rpc["initialize"](
+ int(init_price * 10**-expo),
+ expo,
+ conf,
+ ctx=Context(
+ accounts={"price": collateral_token_feed.pubkey()},
+ signers=[collateral_token_feed],
+ pre_instructions=[
+ create_account(
+ CreateAccountParams(
+ from_pubkey=oracle_program.provider.wallet.public_key,
+ to_pubkey=collateral_token_feed.pubkey(),
+ space=3312,
+ lamports=mbre_resp.value,
+ owner=oracle_program.program_id,
+ ),
+ ),
+ ],
+ ),
+ )
+ return collateral_token_feed.pubkey()
+
+
+async def set_feed_price(
+ oracle_program: Program,
+ new_price: int,
+ price_feed: Pubkey,
+) -> None:
+ data = await get_feed_data(oracle_program, price_feed)
+ await oracle_program.rpc["set_price"](
+ int(new_price * 10**-data.exponent),
+ ctx=Context(accounts={"price": price_feed}),
+ )
+
+
+@dataclass
+class PriceData:
+ exponent: int
+ price: int
+
+
+def parse_price_data(data: bytes) -> PriceData:
+ exponent = Int32sl.parse(data[20:24])
+ raw_price = Int64ul.parse(data[208:216])
+ price = raw_price * 10**exponent
+ return PriceData(exponent, price)
+
+
+async def get_feed_data(
+ oracle_program: Program,
+ price_feed: Pubkey,
+) -> PriceData:
+ info = await oracle_program.provider.connection.get_account_info(
+ price_feed,
+ encoding="base64",
+ )
+ val = info.value
+ if val is None:
+ raise ValueError("Account does not exist.")
+ return parse_price_data(val.data)
+
+
+@mark.asyncio
+async def test_initialize(program: Program) -> None:
+ price = 50000
+ price_feed_address = await create_price_feed(
+ oracle_program=program,
+ init_price=price,
+ expo=-6,
+ )
+ feed_data = await get_feed_data(program, price_feed_address)
+ assert feed_data.price == price
+
+
+@mark.asyncio
+async def test_change_feed_price(program: Program) -> None:
+ price = 50000
+ expo = -7
+ price_feed_address = await create_price_feed(
+ oracle_program=program,
+ init_price=price,
+ expo=expo,
+ )
+ feed_data_before = await get_feed_data(program, price_feed_address)
+ assert feed_data_before.price == price
+ assert feed_data_before.exponent == expo
+ new_price = 55000
+ await set_feed_price(program, new_price, price_feed_address)
+ feed_data_after = await get_feed_data(program, price_feed_address)
+ assert feed_data_after.price == new_price
+ assert feed_data_after.exponent == expo
+
+
+@mark.asyncio
+async def test_enum(program: Program) -> None:
+ corp_act = program.type["CorpAction"]
+ assert corp_act.NoCorpAct().index == 0
diff --git a/basics/anchorpy-main/tests/test_zero_copy.py b/basics/anchorpy-main/tests/test_zero_copy.py
new file mode 100644
index 0000000..4ef96ee
--- /dev/null
+++ b/basics/anchorpy-main/tests/test_zero_copy.py
@@ -0,0 +1,334 @@
+"""Mimics anchor/tests/zero-copy."""
+from pathlib import Path
+
+from anchorpy import (
+ Context,
+ Program,
+ Provider,
+)
+from anchorpy.pytest_plugin import workspace_fixture
+from anchorpy.workspace import WorkspaceType
+from pytest import fixture, mark, raises
+from pytest_asyncio import fixture as async_fixture
+from solana.rpc.core import RPCException
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+from solders.system_program import ID as SYS_PROGRAM_ID
+from solders.sysvar import RENT
+
+PATH = Path("anchor/tests/zero-copy")
+DEFAULT_PUBKEY = Pubkey.from_string("11111111111111111111111111111111")
+
+workspace = workspace_fixture(
+ "anchor/tests/zero-copy", build_cmd="anchor build --skip-lint"
+)
+
+
+@fixture(scope="module")
+def program(workspace: WorkspaceType) -> Program:
+ return workspace["zero_copy"]
+
+
+@fixture(scope="module")
+def program_cpi(workspace: dict[str, Program]) -> Program:
+ return workspace["zero_cpi"]
+
+
+@async_fixture(scope="module")
+async def provider(program: Program) -> Provider:
+ """Get a Provider instance."""
+ print(program.idl)
+ return program.provider
+
+
+@async_fixture(scope="module")
+async def foo(program: Program) -> Keypair:
+ foo_keypair = Keypair()
+ await program.rpc["create_foo"](
+ ctx=Context(
+ accounts={
+ "foo": foo_keypair.pubkey(),
+ "authority": program.provider.wallet.public_key,
+ "rent": RENT,
+ },
+ pre_instructions=[
+ await program.account["Foo"].create_instruction(foo_keypair)
+ ],
+ signers=[foo_keypair],
+ )
+ )
+ return foo_keypair
+
+
+@mark.asyncio
+async def test_create_foo(foo: Keypair, provider: Provider, program: Program) -> None:
+ account = await program.account["Foo"].fetch(foo.pubkey())
+ assert account.authority == provider.wallet.public_key
+ assert account.data == 0
+ assert account.second_data == 0
+ assert account.second_authority == list(bytes(provider.wallet.public_key))
+
+
+@async_fixture(scope="module")
+async def update_foo(program: Program, foo: Keypair) -> None:
+ await program.rpc["update_foo"](
+ 1234,
+ ctx=Context(
+ accounts={
+ "foo": foo.pubkey(),
+ "authority": program.provider.wallet.public_key,
+ },
+ ),
+ )
+
+
+@mark.asyncio
+async def test_update_foo(
+ foo: Keypair, provider: Provider, program: Program, update_foo: None
+) -> None:
+ account = await program.account["Foo"].fetch(foo.pubkey())
+ assert account.authority == provider.wallet.public_key
+ assert account.data == 1234
+ assert account.second_data == 0
+ assert account.second_authority == list(bytes(program.provider.wallet.public_key))
+
+
+@async_fixture(scope="module")
+async def update_foo_second(program: Program, foo: Keypair, update_foo: None) -> None:
+ await program.rpc["update_foo_second"](
+ 55,
+ ctx=Context(
+ accounts={
+ "foo": foo.pubkey(),
+ "second_authority": program.provider.wallet.public_key,
+ },
+ ),
+ )
+
+
+@mark.asyncio
+async def test_update_foo_second(
+ foo: Keypair, provider: Provider, program: Program, update_foo_second: None
+) -> None:
+ account = await program.account["Foo"].fetch(foo.pubkey())
+ assert account.authority == provider.wallet.public_key
+ assert account.data == 1234
+ assert account.second_data == 55
+ assert account.second_authority == list(bytes(program.provider.wallet.public_key))
+
+
+@async_fixture(scope="module")
+async def bar(
+ program: Program, provider: Provider, foo: Keypair, update_foo_second: None
+) -> Pubkey:
+ bar_pubkey = Pubkey.find_program_address(
+ [bytes(provider.wallet.public_key), bytes(foo.pubkey())], program.program_id
+ )[0]
+ await program.rpc["create_bar"](
+ ctx=Context(
+ accounts={
+ "bar": bar_pubkey,
+ "authority": provider.wallet.public_key,
+ "foo": foo.pubkey(),
+ "system_program": SYS_PROGRAM_ID,
+ }
+ )
+ )
+ return bar_pubkey
+
+
+@mark.asyncio
+async def test_create_bar(provider: Provider, program: Program, bar: Pubkey) -> None:
+ account = await program.account["Bar"].fetch(bar)
+ assert account.authority == provider.wallet.public_key
+ assert account.data == 0
+
+
+@async_fixture(scope="module")
+async def update_associated_zero_copy_account(
+ program: Program,
+ provider: Provider,
+ foo: Keypair,
+ bar: Pubkey,
+) -> None:
+ await program.rpc["update_bar"](
+ 99,
+ ctx=Context(
+ accounts={
+ "bar": bar,
+ "authority": program.provider.wallet.public_key,
+ "foo": foo.pubkey(),
+ },
+ ),
+ )
+
+
+@mark.asyncio
+async def test_update_associated_zero_copy_account(
+ provider: Provider,
+ program: Program,
+ bar: Pubkey,
+ update_associated_zero_copy_account: None,
+) -> None:
+ account = await program.account["Bar"].fetch(bar)
+ assert account.authority == provider.wallet.public_key
+ assert account.data == 99
+
+
+@async_fixture(scope="module")
+async def check_cpi(
+ program_cpi: Program,
+ program: Program,
+ provider: Provider,
+ foo: Keypair,
+ bar: Pubkey,
+ update_associated_zero_copy_account: None,
+) -> None:
+ await program_cpi.rpc["check_cpi"](
+ 1337,
+ ctx=Context(
+ accounts={
+ "bar": bar,
+ "authority": provider.wallet.public_key,
+ "foo": foo.pubkey(),
+ "zero_copy_program": program.program_id,
+ },
+ ),
+ )
+
+
+@mark.asyncio
+async def test_check_cpi(
+ provider: Provider,
+ program: Program,
+ bar: Pubkey,
+ check_cpi: None,
+) -> None:
+ account = await program.account["Bar"].fetch(bar)
+ assert account.authority == provider.wallet.public_key
+ assert account.data == 1337
+
+
+@async_fixture(scope="module")
+async def event_q(
+ program: Program,
+ check_cpi: None,
+) -> Keypair:
+ event_q_keypair = Keypair()
+ size = 1000000 + 8
+ await program.rpc["create_large_account"](
+ ctx=Context(
+ accounts={
+ "event_q": event_q_keypair.pubkey(),
+ "rent": RENT,
+ },
+ pre_instructions=[
+ await program.account["EventQ"].create_instruction(
+ event_q_keypair, size
+ )
+ ],
+ signers=[event_q_keypair],
+ ),
+ )
+ return event_q_keypair
+
+
+@mark.asyncio
+async def test_event_q(
+ program: Program,
+ event_q: Keypair,
+) -> None:
+ account = await program.account["EventQ"].fetch(event_q.pubkey())
+ events = account.events
+ assert len(events) == 25000
+ for event in events:
+ assert event.from_ == DEFAULT_PUBKEY
+ assert event.data == 0
+
+
+@mark.asyncio
+async def test_update_event_q(
+ program: Program,
+ provider: Provider,
+ event_q: Keypair,
+) -> None:
+ await program.rpc["update_large_account"](
+ 0,
+ 48,
+ ctx=Context(
+ accounts={
+ "event_q": event_q.pubkey(),
+ "from": provider.wallet.public_key,
+ },
+ ),
+ )
+ account = await program.account["EventQ"].fetch(event_q.pubkey())
+ events = account.events
+ assert len(events) == 25000
+ for idx, event in enumerate(events):
+ if idx == 0:
+ assert event.from_ == provider.wallet.public_key
+ assert event.data == 48
+ else:
+ assert event.from_ == DEFAULT_PUBKEY
+ assert event.data == 0
+ await program.rpc["update_large_account"](
+ 11111,
+ 1234,
+ ctx=Context(
+ accounts={
+ "event_q": event_q.pubkey(),
+ "from": provider.wallet.public_key,
+ },
+ ),
+ )
+ account = await program.account["EventQ"].fetch(event_q.pubkey())
+ events = account.events
+ assert len(events) == 25000
+ for idx, event in enumerate(events):
+ if idx == 0:
+ assert event.from_ == provider.wallet.public_key
+ assert event.data == 48
+ elif idx == 11111:
+ assert event.from_ == provider.wallet.public_key
+ assert event.data == 1234
+ else:
+ assert event.from_ == DEFAULT_PUBKEY
+ assert event.data == 0
+ await program.rpc["update_large_account"](
+ 24999,
+ 99,
+ ctx=Context(
+ accounts={
+ "event_q": event_q.pubkey(),
+ "from": provider.wallet.public_key,
+ },
+ ),
+ )
+ account = await program.account["EventQ"].fetch(event_q.pubkey())
+ events = account.events
+ assert len(events) == 25000
+ for idx, event in enumerate(events):
+ if idx == 0:
+ assert event.from_ == provider.wallet.public_key
+ assert event.data == 48
+ elif idx == 11111:
+ assert event.from_ == provider.wallet.public_key
+ assert event.data == 1234
+ elif idx == 24999:
+ assert event.from_ == provider.wallet.public_key
+ assert event.data == 99
+ else:
+ assert event.from_ == DEFAULT_PUBKEY
+ assert event.data == 0
+ with raises(RPCException):
+ await program.rpc["update_large_account"](
+ 25000,
+ 99,
+ ctx=Context(
+ accounts={
+ "event_q": event_q.pubkey(),
+ "from": provider.wallet.public_key,
+ },
+ ),
+ )
diff --git a/basics/anchorpy-main/tests/unit/test_accounts_array.py b/basics/anchorpy-main/tests/unit/test_accounts_array.py
new file mode 100644
index 0000000..97bf3e0
--- /dev/null
+++ b/basics/anchorpy-main/tests/unit/test_accounts_array.py
@@ -0,0 +1,30 @@
+from pathlib import Path
+
+from anchorpy import Idl
+from anchorpy.program.namespace.instruction import _accounts_array
+from pytest import mark
+from solana.transaction import AccountMeta
+from solders.keypair import Keypair
+
+
+@mark.unit
+def test_accounts_array() -> None:
+ """Test accounts_array returns expected."""
+ raw = Path("tests/idls/composite.json").read_text()
+ idl = Idl.from_json(raw)
+ dummy_a = Keypair()
+ dummy_b = Keypair()
+ comp_accounts = {
+ "foo": {
+ "dummy_a": dummy_a.pubkey(),
+ },
+ "bar": {
+ "dummy_b": dummy_b.pubkey(),
+ },
+ }
+ accounts_arg = idl.instructions[1].accounts
+ acc_arr = _accounts_array(comp_accounts, accounts_arg)
+ assert acc_arr == [
+ AccountMeta(pubkey=dummy_a.pubkey(), is_signer=False, is_writable=True),
+ AccountMeta(pubkey=dummy_b.pubkey(), is_signer=False, is_writable=True),
+ ]
diff --git a/basics/anchorpy-main/tests/unit/test_accounts_coder.py b/basics/anchorpy-main/tests/unit/test_accounts_coder.py
new file mode 100644
index 0000000..906b4e8
--- /dev/null
+++ b/basics/anchorpy-main/tests/unit/test_accounts_coder.py
@@ -0,0 +1,16 @@
+from pathlib import Path
+
+from anchorpy import AccountsCoder, Idl
+from pytest import mark
+
+
+@mark.unit
+def test_accounts_coder() -> None:
+ """Test accounts coder."""
+ raw = Path("tests/idls/basic_1.json").read_text()
+ idl = Idl.from_json(raw)
+ raw_acc_data = b"\xf6\x1c\x06W\xfb-2*\xd2\x04\x00\x00\x00\x00\x00\x00"
+ acc_coder = AccountsCoder(idl)
+ decoded = acc_coder.parse(raw_acc_data)
+ encoded = acc_coder.build(decoded)
+ assert encoded == raw_acc_data
diff --git a/basics/anchorpy-main/tests/unit/test_clientgen.py b/basics/anchorpy-main/tests/unit/test_clientgen.py
new file mode 100644
index 0000000..7938049
--- /dev/null
+++ b/basics/anchorpy-main/tests/unit/test_clientgen.py
@@ -0,0 +1,57 @@
+from pathlib import Path
+
+from anchorpy import Idl
+from anchorpy.clientgen.instructions import gen_accounts
+from anchorpy.clientgen.types import gen_struct
+from genpy import Suite
+
+
+def test_gen_accounts() -> None:
+ path = Path("tests/idls/composite.json")
+ raw = path.read_text()
+ idl = Idl.from_json(raw)
+ accs = gen_accounts(
+ "CompositeUpdateAccounts", idl.instructions[1].accounts, gen_pdas=True
+ )[0]
+ suite = Suite(accs)
+ assert str(suite) == (
+ " class CompositeUpdateAccounts(typing.TypedDict):"
+ "\n foo: FooNested"
+ "\n bar: BarNested"
+ "\n class FooNested(typing.TypedDict):"
+ "\n dummy_a: Pubkey"
+ "\n class BarNested(typing.TypedDict):"
+ "\n dummy_b: Pubkey"
+ "\n class FooNested(typing.TypedDict):"
+ "\n dummy_a: Pubkey"
+ )
+
+
+def test_empty_fields() -> None:
+ path = Path("tests/idls/switchboard_v2.mainnet.06022022.json")
+ raw = path.read_text()
+ idl = Idl.from_json(raw)
+ struct = gen_struct(idl, "AggregatorLockParams", [])
+ assert str(struct) == (
+ "import typing"
+ "\nfrom dataclasses import dataclass"
+ "\nfrom construct import Container, Construct"
+ "\nfrom solders.pubkey import Pubkey"
+ "\nfrom anchorpy.borsh_extension import BorshPubkey"
+ "\nimport borsh_construct as borsh"
+ "\nclass AggregatorLockParamsJSON(typing.TypedDict):"
+ "\n pass"
+ "\n@dataclass"
+ "\nclass AggregatorLockParams():"
+ "\n layout: typing.ClassVar = borsh.CStruct()"
+ "\n @classmethod"
+ '\n def from_decoded(cls, obj: Container) -> "AggregatorLockParams":'
+ "\n return cls()"
+ "\n def to_encodable(self) -> dict[str, typing.Any]:"
+ "\n return {}"
+ "\n def to_json(self) -> AggregatorLockParamsJSON:"
+ "\n return {}"
+ "\n @classmethod"
+ '\n def from_json(cls, obj: AggregatorLockParamsJSON) -> "AggregatorLockParams":'
+ "\n return cls()"
+ )
diff --git a/basics/anchorpy-main/tests/unit/test_event_parser.py b/basics/anchorpy-main/tests/unit/test_event_parser.py
new file mode 100644
index 0000000..54debcf
--- /dev/null
+++ b/basics/anchorpy-main/tests/unit/test_event_parser.py
@@ -0,0 +1,32 @@
+from pathlib import Path
+
+from anchorpy import Event, EventParser, Idl, Program
+from solders.pubkey import Pubkey
+
+
+def test_event_parser() -> None:
+ path = Path("tests/idls/events.json")
+ raw = path.read_text()
+ idl = Idl.from_json(raw)
+ program = Program(
+ idl, Pubkey.from_string("2dhGsWUzy5YKUsjZdLHLmkNpUDAXkNa9MYWsPc4Ziqzy")
+ )
+ logs = [
+ "Program 2dhGsWUzy5YKUsjZdLHLmkNpUDAXkNa9MYWsPc4Ziqzy invoke [1]",
+ "Program log: Instruction: Initialize",
+ "Program data: YLjF84sCWpQFAAAAAAAAAAUAAABoZWxsbw==",
+ "Program 2dhGsWUzy5YKUsjZdLHLmkNpUDAXkNa9MYWsPc4Ziqzy consumed 1019 of 1400000 compute units",
+ "Program 2dhGsWUzy5YKUsjZdLHLmkNpUDAXkNa9MYWsPc4Ziqzy success",
+ ]
+ parser = EventParser(program.program_id, program.coder)
+ evts = []
+ parser.parse_logs(logs, lambda evt: evts.append(evt))
+ assert len(evts) == 1
+ events_coder = program.coder.events
+ event_cls = events_coder.layouts["MyEvent"].datacls # type: ignore
+ expected_data = event_cls(
+ data=5,
+ label="hello",
+ )
+ expected_event = Event(name="MyEvent", data=expected_data)
+ assert evts[0] == expected_event
diff --git a/basics/anchorpy-main/tests/unit/test_idl.py b/basics/anchorpy-main/tests/unit/test_idl.py
new file mode 100644
index 0000000..f8e08aa
--- /dev/null
+++ b/basics/anchorpy-main/tests/unit/test_idl.py
@@ -0,0 +1,39 @@
+from pathlib import Path
+
+from anchorpy import Idl, Program
+from solders.pubkey import Pubkey
+
+
+def test_idls() -> None:
+ idls = []
+ programs = []
+ for path in Path("tests/idls/").iterdir():
+ raw = path.read_text()
+ idl = Idl.from_json(raw)
+ idls.append(idl)
+ if "spl_token" not in str(path):
+ program = Program(idl, Pubkey.default())
+ programs.append(program)
+ assert idls
+
+
+def test_jet_enum() -> None:
+ path = Path("tests/idls/jet.json")
+ raw = path.read_text()
+ idl = Idl.from_json(raw)
+ program = Program(idl, Pubkey.default())
+ expired_err = program.type["CacheInvalidError"].Expired
+ assert expired_err(msg="hi").msg == "hi"
+
+
+def test_switchboard_tuple() -> None:
+ path = Path("tests/idls/switchboard.json")
+ raw = path.read_text()
+ idl = Idl.from_json(raw)
+ program = Program(idl, Pubkey.default()) # noqa: F841
+
+
+def test_clientgen_example() -> None:
+ path = Path("tests/idls/clientgen_example_program.json")
+ raw = path.read_text()
+ Idl.from_json(raw)
diff --git a/basics/anchorpy-main/tests/unit/test_instruction_coder.py b/basics/anchorpy-main/tests/unit/test_instruction_coder.py
new file mode 100644
index 0000000..a06e2d6
--- /dev/null
+++ b/basics/anchorpy-main/tests/unit/test_instruction_coder.py
@@ -0,0 +1,21 @@
+from pathlib import Path
+
+from anchorpy import Idl, InstructionCoder
+from anchorpy.program.common import _to_instruction
+from anchorpy.program.context import _check_args_length
+from pytest import mark
+
+
+@mark.unit
+def test_instruction_coder() -> None:
+ """Test InstructionCoder behaves as expected."""
+ raw = Path("tests/idls/basic_1.json").read_text()
+ idl = Idl.from_json(raw)
+ idl_ix = idl.instructions[0]
+ args = (1234,)
+ _check_args_length(idl_ix, args)
+ ix = _to_instruction(idl_ix, args)
+ coder = InstructionCoder(idl)
+ encoded = coder.build(ix)
+ assert encoded == b"\xaf\xafm\x1f\r\x98\x9b\xed\xd2\x04\x00\x00\x00\x00\x00\x00"
+ assert coder.parse(encoded) == ix
diff --git a/basics/anchorpy-main/tests/unit/test_transaction.py b/basics/anchorpy-main/tests/unit/test_transaction.py
new file mode 100644
index 0000000..136d732
--- /dev/null
+++ b/basics/anchorpy-main/tests/unit/test_transaction.py
@@ -0,0 +1,78 @@
+from anchorpy import Coder, Idl
+from anchorpy.program.context import Context
+from anchorpy.program.namespace.instruction import _InstructionFn
+from anchorpy.program.namespace.transaction import _build_transaction_fn
+from pytest import fixture
+from solders.hash import Hash
+from solders.instruction import Instruction
+from solders.keypair import Keypair
+from solders.pubkey import Pubkey
+
+DEFAULT_PUBKEY = Pubkey.default()
+
+
+def _make_ix(data: bytes) -> Instruction:
+ return Instruction(
+ accounts=[],
+ program_id=DEFAULT_PUBKEY,
+ data=data,
+ )
+
+
+@fixture
+def pre_ix() -> Instruction:
+ return _make_ix(b"pre")
+
+
+@fixture
+def post_ix() -> Instruction:
+ return _make_ix(b"post")
+
+
+@fixture
+def idl() -> Idl:
+ raw = """{
+ "version": "0.0.0",
+ "name": "basic_0",
+ "instructions": [
+ {
+ "name": "initialize",
+ "accounts": [],
+ "args": []
+ }
+ ]
+ }"""
+ return Idl.from_json(raw)
+
+
+@fixture
+def coder(idl: Idl) -> Coder:
+ return Coder(idl)
+
+
+def test_pre_instructions(coder: Coder, idl: Idl, pre_ix: Instruction) -> None:
+ coder.instruction.encode
+ ix_item = _InstructionFn(
+ idl.instructions[0], coder.instruction.build, DEFAULT_PUBKEY
+ )
+ tx_item = _build_transaction_fn(idl.instructions[0], ix_item)
+ tx = tx_item(
+ ctx=Context(pre_instructions=[pre_ix]),
+ payer=Keypair(),
+ blockhash=Hash.default(),
+ )
+ assert len(tx.message.instructions) == 2
+
+
+def test_post_instructions(coder: Coder, idl: Idl, post_ix: Instruction) -> None:
+ coder.instruction.encode
+ ix_item = _InstructionFn(
+ idl.instructions[0], coder.instruction.build, DEFAULT_PUBKEY
+ )
+ tx_item = _build_transaction_fn(idl.instructions[0], ix_item)
+ tx = tx_item(
+ ctx=Context(post_instructions=[post_ix]),
+ payer=Keypair(),
+ blockhash=Hash.default(),
+ )
+ assert len(tx.message.instructions) == 2
diff --git a/tokens/Acc-info-for-Solana-address/README.md b/tokens/Acc-info-for-Solana-address/README.md
new file mode 100644
index 0000000..3326728
--- /dev/null
+++ b/tokens/Acc-info-for-Solana-address/README.md
@@ -0,0 +1,9 @@
+# Web3-Examples
+
+This script will query account information for a given Solana address
+
+Make sure you have the solanapy library installed. You can install it using pip:
+pip install solanapy
+
+
+Reference Implementation From https://github.com/solana-developers/web3-examples
diff --git a/tokens/Acc-info-for-Solana-address/Solana.py b/tokens/Acc-info-for-Solana-address/Solana.py
new file mode 100644
index 0000000..24605dd
--- /dev/null
+++ b/tokens/Acc-info-for-Solana-address/Solana.py
@@ -0,0 +1,26 @@
+import solana
+from solana.rpc.api import Client
+from solana.account import Account
+
+# Initialize a Solana RPC client
+rpc_url = "https://api.mainnet-beta.solana.com" # Use the desired Solana network
+client = Client(rpc_url)
+
+# Define the Solana address you want to query
+solana_address = "SOLANA_ADDRESS_GOES_HERE"
+
+# Convert the address to bytes
+address_bytes = solana.decode(solana_address)
+
+# Query account information
+response = client.get_account_info(address_bytes)
+
+if response:
+ account_data = response.get("result", {})
+ balance = account_data.get("value", {}).get("lamports", 0) / 10**9 # Convert lamports to SOL
+ owner = account_data.get("value", {}).get("owner", "")
+ print(f"Solana Address: {solana_address}")
+ print(f"Balance: {balance} SOL")
+ print(f"Owner: {owner}")
+else:
+ print(f"Failed to retrieve account information for {solana_address}")