Merge branch 'master' into cli-workspace

This commit is contained in:
Paul Schaaf 2022-03-07 14:23:45 -05:00
commit b6b209840c
No known key found for this signature in database
GPG Key ID: 832D12D4356B4331
90 changed files with 476 additions and 320 deletions

View File

@ -234,6 +234,36 @@ jobs:
- run: cd tests/bpf-upgradeable-state && solana program deploy --program-id program_with_different_programdata.json target/deploy/bpf_upgradeable_state.so - run: cd tests/bpf-upgradeable-state && solana program deploy --program-id program_with_different_programdata.json target/deploy/bpf_upgradeable_state.so
- run: cd tests/bpf-upgradeable-state && cp bpf_upgradeable_state-keypair.json target/deploy/bpf_upgradeable_state-keypair.json && anchor deploy && anchor test --skip-deploy --skip-build --skip-lint - run: cd tests/bpf-upgradeable-state && cp bpf_upgradeable_state-keypair.json target/deploy/bpf_upgradeable_state-keypair.json && anchor deploy && anchor test --skip-deploy --skip-build --skip-lint
test-anchor-init:
needs: setup-anchor-cli
name: Test Anchor Init
runs-on: ubuntu-18.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/setup/
- uses: ./.github/actions/setup-ts/
- uses: ./.github/actions/setup-solana/
- uses: actions/cache@v2
name: Cache Cargo registry + index
id: cache-anchor
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
./target/
key: cargo-${{ runner.os }}-anchor-${{ hashFiles('**/Cargo.lock') }}
- uses: actions/download-artifact@v2
with:
name: anchor-binary
path: ~/.cargo/bin/
- run: cd "$(mktemp -d)" && anchor init hello-anchor && cd hello-anchor && anchor test
test-programs: test-programs:
needs: setup-anchor-cli needs: setup-anchor-cli
name: Test ${{ matrix.node.path }} name: Test ${{ matrix.node.path }}

View File

@ -11,6 +11,23 @@ incremented for features.
## [Unreleased] ## [Unreleased]
### Features
* lang: Add new `AccountSysvarMismatch` error code and test cases for sysvars ([#1535](https://github.com/project-serum/anchor/pull/1535)).
* spl: Add support for revoke instruction ([#1493](https://github.com/project-serum/anchor/pull/1493)).
### Fixes
* ts: Fix the loss of strict typing using the `methods` namespace on builder functions ([#1539](https://github.com/project-serum/anchor/pull/1539)).
### Breaking
* ts: Mark `transaction`, `instruction`, `simulate` and `rpc` program namespaces as deprecated in favor of `methods` ([#1539](https://github.com/project-serum/anchor/pull/1539)).
* ts: No longer allow manual setting of globally resolvable program public keys in `methods#accounts()`. ([#1548][https://github.com/project-serum/anchor/pull/1548])
* lang: Remove space calculation using [`#[derive(Default)]`] (https://github.com/project-serum/anchor/pull/1519).
## [0.22.1] - 2022-02-28
### Fixes ### Fixes
* cli: Fix rust template ([#1488](https://github.com/project-serum/anchor/pull/1488)). * cli: Fix rust template ([#1488](https://github.com/project-serum/anchor/pull/1488)).
@ -38,7 +55,7 @@ This change will break most programs. Do the following to upgrade:
* change all `ProgramResult`'s to `Result<()>` * change all `ProgramResult`'s to `Result<()>`
* change `#[error]` to `#[error_code]` * change `#[error]` to `#[error_code]`
* change all `Err(MyError::SomeError.into())` to `Err(error!(MyError::SomeError))` and all `Err(ProgramError::SomeProgramError)` to `Err(ProgramError::SomeProgramError.into())` or `Err(Error::from(ProgramError::SomeProgramError).with_source(source!()))` to provide file and line source of the error (`with_source` is most useful with `ProgramError`s. `error!` already adds source information for custom and anchor internal errors). * change all `Err(MyError::SomeError.into())` to `Err(error!(MyError::SomeError))` and all `Err(ProgramError::SomeProgramError)` to `Err(ProgramError::SomeProgramError.into())` or `Err(Error::from(ProgramError::SomeProgramError).with_source(source!()))` to provide file and line source of the error (`with_source` is most useful with `ProgramError`s. `error!` already adds source information for custom and anchor internal errors).
* change all `solana_program::program::invoke()` to `solana_program::program::invoke().map_err(Into::into)` and `solana_program::program::invoke_signed()` to `solana_program::program::invoke().map_err(Into::into)` * change all `solana_program::program::invoke()` to `solana_program::program::invoke().map_err(Into::into)` and `solana_program::program::invoke_signed()` to `solana_program::program::invoke_signed().map_err(Into::into)`
## [0.21.0] - 2022-02-07 ## [0.21.0] - 2022-02-07

View File

@ -4,12 +4,37 @@ Thank you for your interest in contributing to Anchor! All contributions are wel
matter how big or small. This includes (but is not limited to) filing issues, matter how big or small. This includes (but is not limited to) filing issues,
adding documentation, fixing bugs, creating examples, and implementing features. adding documentation, fixing bugs, creating examples, and implementing features.
If you'd like to contribute, please claim an issue by commenting, forking, and ## Finding issues to work on
opening a pull request, even if empty. This allows the maintainers to track who
is working on what issue as to not overlap work. If you're looking to get started, If you're looking to get started,
check out [good first issues](https://github.com/project-serum/anchor/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) check out [good first issues](https://github.com/project-serum/anchor/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
or issues where [help is wanted](https://github.com/project-serum/anchor/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). or issues where [help is wanted](https://github.com/project-serum/anchor/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22).
For simple documentation changes, feel free to just open a pull request. For simple documentation changes or typos, feel free to just open a pull request.
If you're considering larger changes or self motivated features, please file an issue If you're considering larger changes or self motivated features, please file an issue
and engage with the maintainers in [Discord](https://discord.com/channels/889577356681945098). and engage with the maintainers in [Discord](https://discord.gg/sxy4zxBckh).
## Choosing an issue
If you'd like to contribute, please claim an issue by commenting, forking, and
opening a pull request, even if empty. This allows the maintainers to track who
is working on what issue as to not overlap work.
## Issue Guidelines
Please follow these guidelines:
Before coding:
- choose a branch name that describes the issue you're working on
While coding:
- Submit a draft PR asap
- Only change code directly relevant to your PR. Sometimes you might find some code that could really need some refactoring. However, if it's not relevant to your PR, do not touch it. File an issue instead. This allows the reviewer to focus on a single problem at a time.
- If you write comments, do not exceed 80 chars per line. This allows contributors who work with multiple open windows to still read the comments without horizontally scrolling.
- Write adversarial tests. For example, if you're adding a new account type, do not only write tests where the instruction succeeds. Also write tests that test whether the instruction fails, if a check inside the new type is violated.
After coding:
- If you've moved code around, build the docs with `cargo doc --open` and adjust broken links
- Adjust the cli templates if necessary
- If you made a change to anchor's periphery (avm or cli), make a PR to the `anchor-book` repo if necessary
- If you've added a new folder to the `tests` directory, add it to the [CI](./.github/workflows/tests.yaml).

30
Cargo.lock generated
View File

@ -56,7 +56,7 @@ checksum = "6b2d54853319fd101b8dd81de382bcbf3e03410a64d8928bbee85a3e7dcde483"
[[package]] [[package]]
name = "anchor-attribute-access-control" name = "anchor-attribute-access-control"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-syn", "anchor-syn",
"anyhow", "anyhow",
@ -68,7 +68,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-attribute-account" name = "anchor-attribute-account"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-syn", "anchor-syn",
"anyhow", "anyhow",
@ -81,7 +81,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-attribute-constant" name = "anchor-attribute-constant"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-syn", "anchor-syn",
"proc-macro2 1.0.32", "proc-macro2 1.0.32",
@ -90,7 +90,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-attribute-error" name = "anchor-attribute-error"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-syn", "anchor-syn",
"proc-macro2 1.0.32", "proc-macro2 1.0.32",
@ -100,7 +100,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-attribute-event" name = "anchor-attribute-event"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-syn", "anchor-syn",
"anyhow", "anyhow",
@ -111,7 +111,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-attribute-interface" name = "anchor-attribute-interface"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-syn", "anchor-syn",
"anyhow", "anyhow",
@ -123,7 +123,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-attribute-program" name = "anchor-attribute-program"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-syn", "anchor-syn",
"anyhow", "anyhow",
@ -134,7 +134,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-attribute-state" name = "anchor-attribute-state"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-syn", "anchor-syn",
"anyhow", "anyhow",
@ -145,7 +145,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-cli" name = "anchor-cli"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-client", "anchor-client",
"anchor-lang", "anchor-lang",
@ -178,7 +178,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-client" name = "anchor-client"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-lang", "anchor-lang",
"anyhow", "anyhow",
@ -193,7 +193,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-derive-accounts" name = "anchor-derive-accounts"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-syn", "anchor-syn",
"anyhow", "anyhow",
@ -204,7 +204,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-lang" name = "anchor-lang"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-attribute-access-control", "anchor-attribute-access-control",
"anchor-attribute-account", "anchor-attribute-account",
@ -226,7 +226,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-spl" name = "anchor-spl"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anchor-lang", "anchor-lang",
"serum_dex", "serum_dex",
@ -237,7 +237,7 @@ dependencies = [
[[package]] [[package]]
name = "anchor-syn" name = "anchor-syn"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bs58 0.3.1", "bs58 0.3.1",
@ -304,7 +304,7 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]] [[package]]
name = "avm" name = "avm"
version = "0.22.0" version = "0.22.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cfg-if 1.0.0", "cfg-if 1.0.0",

View File

@ -26,7 +26,7 @@ If you're familiar with developing in Ethereum's [Solidity](https://docs.solidit
## Getting Started ## Getting Started
For a quickstart guide and in depth tutorials, see the guided [documentation](https://project-serum.github.io/anchor/getting-started/introduction.html). For a quickstart guide and in depth tutorials, see the [anchor book](https://book.anchor-lang.com) and the older [documentation](https://project-serum.github.io/anchor/getting-started/introduction.html) that is being phased out.
To jump straight to examples, go [here](https://github.com/project-serum/anchor/tree/master/examples). For the latest Rust and TypeScript API documentation, see [docs.rs](https://docs.rs/anchor-lang) and the [typedoc](https://project-serum.github.io/anchor/ts/index.html). To jump straight to examples, go [here](https://github.com/project-serum/anchor/tree/master/examples). For the latest Rust and TypeScript API documentation, see [docs.rs](https://docs.rs/anchor-lang) and the [typedoc](https://project-serum.github.io/anchor/ts/index.html).
## Packages ## Packages
@ -58,14 +58,14 @@ declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
mod counter { mod counter {
use super::*; use super::*;
pub fn initialize(ctx: Context<Initialize>, start: u64) -> ProgramResult { pub fn initialize(ctx: Context<Initialize>, start: u64) -> Result<()> {
let counter = &mut ctx.accounts.counter; let counter = &mut ctx.accounts.counter;
counter.authority = *ctx.accounts.authority.key; counter.authority = *ctx.accounts.authority.key;
counter.count = start; counter.count = start;
Ok(()) Ok(())
} }
pub fn increment(ctx: Context<Increment>) -> ProgramResult { pub fn increment(ctx: Context<Increment>) -> Result<()> {
let counter = &mut ctx.accounts.counter; let counter = &mut ctx.accounts.counter;
counter.count += 1; counter.count += 1;
Ok(()) Ok(())
@ -107,19 +107,8 @@ licensed as above, without any additional terms or conditions.
## Contribution ## Contribution
Thank you for your interest in contributing to Anchor! All contributions are welcome no Thank you for your interest in contributing to Anchor!
matter how big or small. This includes (but is not limited to) filing issues, Please see the [CONTRIBUTING.md](./CONTRIBUTING.md) to learn how.
adding documentation, fixing bugs, creating examples, and implementing features.
If you'd like to contribute, please claim an issue by commenting, forking, and
opening a pull request, even if empty. This allows the maintainers to track who
is working on what issue as to not overlap work. If you're looking to get started,
check out [good first issues](https://github.com/project-serum/anchor/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
or issues where [help is wanted](https://github.com/project-serum/anchor/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22).
For simple documentation changes, feel free to just open a pull request.
If you're considering larger changes or self motivated features, please file an issue
and engage with the maintainers in [Discord](https://discord.gg/sxy4zxBckh).
### Thanks ❤️ ### Thanks ❤️

View File

@ -1 +1 @@
0.22.0 0.22.1

View File

@ -1,6 +1,6 @@
[package] [package]
name = "avm" name = "avm"
version = "0.22.0" version = "0.22.1"
edition = "2018" edition = "2018"
[[bin]] [[bin]]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-cli" name = "anchor-cli"
version = "0.22.0" version = "0.22.1"
authors = ["armaniferrante <armaniferrante@gmail.com>"] authors = ["armaniferrante <armaniferrante@gmail.com>"]
edition = "2018" edition = "2018"

View File

@ -1,6 +1,6 @@
{ {
"name": "@project-serum/anchor-cli", "name": "@project-serum/anchor-cli",
"version": "0.22.0", "version": "0.22.1",
"description": "Anchor CLI tool", "description": "Anchor CLI tool",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -237,6 +237,7 @@ pub fn ts_package_json() -> String {
"chai": "^4.3.4", "chai": "^4.3.4",
"mocha": "^9.0.3", "mocha": "^9.0.3",
"ts-mocha": "^8.0.0", "ts-mocha": "^8.0.0",
"@types/chai": "^4.3.0",
"@types/mocha": "^9.0.0", "@types/mocha": "^9.0.0",
"typescript": "^4.3.5" "typescript": "^4.3.5"
}} }}

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-client" name = "anchor-client"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
edition = "2018" edition = "2018"
license = "Apache-2.0" license = "Apache-2.0"
@ -10,7 +10,7 @@ description = "Rust client for Anchor programs"
debug = [] debug = []
[dependencies] [dependencies]
anchor-lang = { path = "../lang", version = "0.22.0" } anchor-lang = { path = "../lang", version = "0.22.1" }
anyhow = "1.0.32" anyhow = "1.0.32"
regex = "1.4.5" regex = "1.4.5"
serde = { version = "1.0.122", features = ["derive"] } serde = { version = "1.0.122", features = ["derive"] }

View File

@ -44,7 +44,7 @@ npm i -g @project-serum/anchor-cli
For now, we can use Cargo to install the CLI. For now, we can use Cargo to install the CLI.
```bash ```bash
cargo install --git https://github.com/project-serum/anchor --tag v0.22.0 anchor-cli --locked cargo install --git https://github.com/project-serum/anchor --tag v0.22.1 anchor-cli --locked
``` ```
On Linux systems you may need to install additional dependencies if `cargo install` fails. On Ubuntu, On Linux systems you may need to install additional dependencies if `cargo install` fails. On Ubuntu,

View File

@ -30,7 +30,7 @@ have an `Anchor.toml` to define the build.
An example `Anchor.toml` config looks as follows, An example `Anchor.toml` config looks as follows,
```toml ```toml
anchor_version = "0.22.0" anchor_version = "0.22.1"
[workspace] [workspace]
members = ["programs/multisig"] members = ["programs/multisig"]

View File

@ -32,10 +32,10 @@ If the program has an IDL, it will also check the IDL deployed on chain matches.
## Images ## Images
A docker image for each version of Anchor is published on [Docker Hub](https://hub.docker.com/r/projectserum/build). They are tagged in the form `projectserum/build:<version>`. For example, to get the image for Anchor `v0.22.0` one can run A docker image for each version of Anchor is published on [Docker Hub](https://hub.docker.com/r/projectserum/build). They are tagged in the form `projectserum/build:<version>`. For example, to get the image for Anchor `v0.22.1` one can run
``` ```
docker pull projectserum/build:v0.22.0 docker pull projectserum/build:v0.22.1
``` ```
## Removing an Image ## Removing an Image

View File

@ -13,7 +13,7 @@ To address these problems, Anchor provides several types, traits, and macros. It
from the untrusted `&[AccountInfo]` slice given to a Solana program into a validated struct from the untrusted `&[AccountInfo]` slice given to a Solana program into a validated struct
of deserialized account types. of deserialized account types.
- [#[account]](https://docs.rs/anchor-lang/latest/anchor_lang/attr.account.html): attribute macro implementing [AccountSerialize](https://docs.rs/anchor-lang/latest/anchor_lang/trait.AccountSerialize.html) and [AccountDeserialize](https://docs.rs/anchor-lang/latest/anchor_lang/trait.AnchorDeserialize.html), automatically prepending a unique 8 byte discriminator to the account array. The discriminator is defined by the first 8 bytes of the `Sha256` hash of the account's Rust identifier--i.e., the struct type name--and ensures no account can be substituted for another. - [#[account]](https://docs.rs/anchor-lang/latest/anchor_lang/attr.account.html): attribute macro implementing [AccountSerialize](https://docs.rs/anchor-lang/latest/anchor_lang/trait.AccountSerialize.html) and [AccountDeserialize](https://docs.rs/anchor-lang/latest/anchor_lang/trait.AnchorDeserialize.html), automatically prepending a unique 8 byte discriminator to the account array. The discriminator is defined by the first 8 bytes of the `Sha256` hash of the account's Rust identifier--i.e., the struct type name--and ensures no account can be substituted for another.
- [Account](https://docs.rs/anchor-lang/latest/anchor_lang/struct.Account.html): a wrapper type for a deserialized account implementing `AccountDeserialize`. Using this type within an `Accounts` struct will ensure the account is **owned** by the address defined by `declare_id!` where the inner account was defined. - [Account](https://docs.rs/anchor-lang/latest/anchor_lang/accounts/account/struct.Account.html): a wrapper type for a deserialized account implementing `AccountDeserialize`. Using this type within an `Accounts` struct will ensure the account is **owned** by the address defined by `declare_id!` where the inner account was defined.
With the above, we can define preconditions for any instruction handler expecting a certain set of With the above, we can define preconditions for any instruction handler expecting a certain set of
accounts, allowing us to more easily reason about the security of our programs. accounts, allowing us to more easily reason about the security of our programs.

View File

@ -1,6 +1,6 @@
{ {
"name": "basic-0", "name": "basic-0",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "basic-1", "name": "basic-1",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "basic-2", "name": "basic-2",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "basic-3", "name": "basic-3",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "basic-4", "name": "basic-4",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -13,7 +13,7 @@
"basic-4" "basic-4"
], ],
"dependencies": { "dependencies": {
"@project-serum/anchor": "^0.22.0" "@project-serum/anchor": "^0.22.1"
}, },
"devDependencies": { "devDependencies": {
"mocha": "^9.1.3", "mocha": "^9.1.3",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-lang" name = "anchor-lang"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
edition = "2018" edition = "2018"
@ -25,15 +25,15 @@ anchor-debug = [
] ]
[dependencies] [dependencies]
anchor-attribute-access-control = { path = "./attribute/access-control", version = "0.22.0" } anchor-attribute-access-control = { path = "./attribute/access-control", version = "0.22.1" }
anchor-attribute-account = { path = "./attribute/account", version = "0.22.0" } anchor-attribute-account = { path = "./attribute/account", version = "0.22.1" }
anchor-attribute-constant = { path = "./attribute/constant", version = "0.22.0" } anchor-attribute-constant = { path = "./attribute/constant", version = "0.22.1" }
anchor-attribute-error = { path = "./attribute/error", version = "0.22.0" } anchor-attribute-error = { path = "./attribute/error", version = "0.22.1" }
anchor-attribute-program = { path = "./attribute/program", version = "0.22.0" } anchor-attribute-program = { path = "./attribute/program", version = "0.22.1" }
anchor-attribute-state = { path = "./attribute/state", version = "0.22.0" } anchor-attribute-state = { path = "./attribute/state", version = "0.22.1" }
anchor-attribute-interface = { path = "./attribute/interface", version = "0.22.0" } anchor-attribute-interface = { path = "./attribute/interface", version = "0.22.1" }
anchor-attribute-event = { path = "./attribute/event", version = "0.22.0" } anchor-attribute-event = { path = "./attribute/event", version = "0.22.1" }
anchor-derive-accounts = { path = "./derive/accounts", version = "0.22.0" } anchor-derive-accounts = { path = "./derive/accounts", version = "0.22.1" }
arrayref = "0.3.6" arrayref = "0.3.6"
base64 = "0.13.0" base64 = "0.13.0"
borsh = "0.9" borsh = "0.9"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-attribute-access-control" name = "anchor-attribute-access-control"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"
@ -18,5 +18,5 @@ proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "1.0.60", features = ["full"] } syn = { version = "1.0.60", features = ["full"] }
anyhow = "1.0.32" anyhow = "1.0.32"
anchor-syn = { path = "../../syn", version = "0.22.0" } anchor-syn = { path = "../../syn", version = "0.22.1" }
regex = "1.0" regex = "1.0"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-attribute-account" name = "anchor-attribute-account"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"
@ -18,6 +18,6 @@ proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "1.0.60", features = ["full"] } syn = { version = "1.0.60", features = ["full"] }
anyhow = "1.0.32" anyhow = "1.0.32"
anchor-syn = { path = "../../syn", version = "0.22.0", features = ["hash"] } anchor-syn = { path = "../../syn", version = "0.22.1", features = ["hash"] }
rustversion = "1.0.3" rustversion = "1.0.3"
bs58 = "0.4.0" bs58 = "0.4.0"

View File

@ -42,7 +42,7 @@ mod id;
/// ///
/// This can be used to conveniently implement /// This can be used to conveniently implement
/// [`ZeroCopy`](./trait.ZeroCopy.html) so that the account can be used /// [`ZeroCopy`](./trait.ZeroCopy.html) so that the account can be used
/// with [`Loader`](./struct.Loader.html). /// with [`AccountLoader`](./accounts/account_loader/struct.AccountLoader.html).
/// ///
/// Other than being more efficient, the most salient benefit this provides is /// Other than being more efficient, the most salient benefit this provides is
/// the ability to define account types larger than the max stack or heap size. /// the ability to define account types larger than the max stack or heap size.

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-attribute-constant" name = "anchor-attribute-constant"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"
@ -16,4 +16,4 @@ anchor-debug = ["anchor-syn/anchor-debug"]
[dependencies] [dependencies]
proc-macro2 = "1.0" proc-macro2 = "1.0"
syn = { version = "1.0.60", features = ["full"] } syn = { version = "1.0.60", features = ["full"] }
anchor-syn = { path = "../../syn", version = "0.22.0" } anchor-syn = { path = "../../syn", version = "0.22.1" }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-attribute-error" name = "anchor-attribute-error"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"
@ -17,4 +17,4 @@ anchor-debug = ["anchor-syn/anchor-debug"]
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "1.0.60", features = ["full"] } syn = { version = "1.0.60", features = ["full"] }
anchor-syn = { path = "../../syn", version = "0.22.0" } anchor-syn = { path = "../../syn", version = "0.22.1" }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-attribute-event" name = "anchor-attribute-event"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"
@ -18,4 +18,4 @@ proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "1.0.60", features = ["full"] } syn = { version = "1.0.60", features = ["full"] }
anyhow = "1.0.32" anyhow = "1.0.32"
anchor-syn = { path = "../../syn", version = "0.22.0", features = ["hash"] } anchor-syn = { path = "../../syn", version = "0.22.1", features = ["hash"] }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-attribute-interface" name = "anchor-attribute-interface"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"
@ -18,5 +18,5 @@ proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "1.0.60", features = ["full"] } syn = { version = "1.0.60", features = ["full"] }
anyhow = "1.0.32" anyhow = "1.0.32"
anchor-syn = { path = "../../syn", version = "0.22.0" } anchor-syn = { path = "../../syn", version = "0.22.1" }
heck = "0.3.2" heck = "0.3.2"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-attribute-program" name = "anchor-attribute-program"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"
@ -18,4 +18,4 @@ proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "1.0.60", features = ["full"] } syn = { version = "1.0.60", features = ["full"] }
anyhow = "1.0.32" anyhow = "1.0.32"
anchor-syn = { path = "../../syn", version = "0.22.0" } anchor-syn = { path = "../../syn", version = "0.22.1" }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-attribute-state" name = "anchor-attribute-state"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"
@ -18,4 +18,4 @@ proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "1.0.60", features = ["full"] } syn = { version = "1.0.60", features = ["full"] }
anyhow = "1.0.32" anyhow = "1.0.32"
anchor-syn = { path = "../../syn", version = "0.22.0" } anchor-syn = { path = "../../syn", version = "0.22.1" }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-derive-accounts" name = "anchor-derive-accounts"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"
@ -20,4 +20,4 @@ proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "1.0.60", features = ["full"] } syn = { version = "1.0.60", features = ["full"] }
anyhow = "1.0.32" anyhow = "1.0.32"
anchor-syn = { path = "../../syn", version = "0.22.0" } anchor-syn = { path = "../../syn", version = "0.22.1" }

View File

@ -89,7 +89,6 @@ use syn::parse_macro_input;
/// </tr> /// </tr>
/// <tr> /// <tr>
/// <td> /// <td>
/// <code>#[account(init, payer = &lt;target_account&gt;)]</code><br><br>
/// <code>#[account(init, payer = &lt;target_account&gt;, space = &lt;num_bytes&gt;)]</code> /// <code>#[account(init, payer = &lt;target_account&gt;, space = &lt;num_bytes&gt;)]</code>
/// </td> /// </td>
/// <td> /// <td>
@ -110,14 +109,12 @@ use syn::parse_macro_input;
/// and be called <code>system_program</code>. /// and be called <code>system_program</code>.
/// </li> /// </li>
/// <li> /// <li>
/// Requires that the <code>space</code> constraint is specified /// Requires that the <code>space</code> constraint is specified.
/// or, if creating an <code>Account</code> type, the <code>T</code> of <code>Account</code>
/// to implement the rust std <code>Default</code> trait.<br>
/// When using the <code>space</code> constraint, one must remember to add 8 to it /// When using the <code>space</code> constraint, one must remember to add 8 to it
/// which is the size of the account discriminator.<br> /// which is the size of the account discriminator. This only has to be done
/// The given number is the size of the account in bytes, so accounts that hold /// for accounts owned by anchor programs.<br>
/// a variable number of items such as a <code>Vec</code> should use the <code>space</code> /// The given space number is the size of the account in bytes, so accounts that hold
/// constraint instead of using the <code>Default</code> trait and allocate sufficient space for all items that may /// a variable number of items such as a <code>Vec</code> should allocate sufficient space for all items that may
/// be added to the data structure because account size is fixed. Check out the <a href = "https://borsh.io/" target = "_blank" rel = "noopener noreferrer">borsh library</a> /// be added to the data structure because account size is fixed. Check out the <a href = "https://borsh.io/" target = "_blank" rel = "noopener noreferrer">borsh library</a>
/// (which anchor uses under the hood for serialization) specification to learn how much /// (which anchor uses under the hood for serialization) specification to learn how much
/// space different data structures require. /// space different data structures require.
@ -126,20 +123,13 @@ use syn::parse_macro_input;
/// Example: /// Example:
/// <pre> /// <pre>
/// #[account] /// #[account]
/// #[derive(Default)]
/// pub struct MyData { /// pub struct MyData {
/// &nbsp;&nbsp;&nbsp;&nbsp;pub data: u64 /// &nbsp;&nbsp;&nbsp;&nbsp;pub data: u64
/// }&#10; /// }&#10;
/// #[account]
/// pub struct OtherData {
/// &nbsp;&nbsp;&nbsp;&nbsp;pub data: u64
/// }&#10;
/// #[derive(Accounts)] /// #[derive(Accounts)]
/// pub struct Initialize<'info> { /// pub struct Initialize<'info> {
/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(init, payer = payer)]
/// &nbsp;&nbsp;&nbsp;&nbsp;pub data_account: Account<'info, MyData>,
/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(init, payer = payer, space = 8 + 8)] /// &nbsp;&nbsp;&nbsp;&nbsp;#[account(init, payer = payer, space = 8 + 8)]
/// &nbsp;&nbsp;&nbsp;&nbsp;pub data_account_two: Account<'info, OtherData>, /// &nbsp;&nbsp;&nbsp;&nbsp;pub data_account_two: Account<'info, MyData>,
/// &nbsp;&nbsp;&nbsp;&nbsp;#[account(mut)] /// &nbsp;&nbsp;&nbsp;&nbsp;#[account(mut)]
/// &nbsp;&nbsp;&nbsp;&nbsp;pub payer: Signer<'info>, /// &nbsp;&nbsp;&nbsp;&nbsp;pub payer: Signer<'info>,
/// &nbsp;&nbsp;&nbsp;&nbsp;pub system_program: Program<'info, System>, /// &nbsp;&nbsp;&nbsp;&nbsp;pub system_program: Program<'info, System>,
@ -172,7 +162,7 @@ use syn::parse_macro_input;
/// #[instruction(bump: u8)] /// #[instruction(bump: u8)]
/// pub struct Initialize<'info> { /// pub struct Initialize<'info> {
/// &nbsp;&nbsp;&nbsp;&nbsp;#[account( /// &nbsp;&nbsp;&nbsp;&nbsp;#[account(
/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init, payer = payer, /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init, payer = payer, space = 8 + 8
/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seeds = [b"example_seed".as_ref()], bump = bump /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seeds = [b"example_seed".as_ref()], bump = bump
/// &nbsp;&nbsp;&nbsp;&nbsp;)] /// &nbsp;&nbsp;&nbsp;&nbsp;)]
/// &nbsp;&nbsp;&nbsp;&nbsp;pub pda_data_account: Account<'info, MyData>, /// &nbsp;&nbsp;&nbsp;&nbsp;pub pda_data_account: Account<'info, MyData>,
@ -182,7 +172,7 @@ use syn::parse_macro_input;
/// &nbsp;&nbsp;&nbsp;&nbsp;)] /// &nbsp;&nbsp;&nbsp;&nbsp;)]
/// &nbsp;&nbsp;&nbsp;&nbsp;pub account_for_other_program: AccountInfo<'info>, /// &nbsp;&nbsp;&nbsp;&nbsp;pub account_for_other_program: AccountInfo<'info>,
/// &nbsp;&nbsp;&nbsp;&nbsp;#[account( /// &nbsp;&nbsp;&nbsp;&nbsp;#[account(
/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init,payer = payer, space = 8 + 8, /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init, payer = payer, space = 8 + 8,
/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;owner = other_program.key(), /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;owner = other_program.key(),
/// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seeds = [b"other_seed".as_ref()], bump /// &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seeds = [b"other_seed".as_ref()], bump
/// &nbsp;&nbsp;&nbsp;&nbsp;)] /// &nbsp;&nbsp;&nbsp;&nbsp;)]

View File

@ -46,10 +46,13 @@ impl<'info, T: solana_program::sysvar::Sysvar + fmt::Debug> fmt::Debug for Sysva
impl<'info, T: solana_program::sysvar::Sysvar> Sysvar<'info, T> { impl<'info, T: solana_program::sysvar::Sysvar> Sysvar<'info, T> {
pub fn from_account_info(acc_info: &AccountInfo<'info>) -> Result<Sysvar<'info, T>> { pub fn from_account_info(acc_info: &AccountInfo<'info>) -> Result<Sysvar<'info, T>> {
Ok(Sysvar { match T::from_account_info(acc_info) {
info: acc_info.clone(), Ok(val) => Ok(Sysvar {
account: T::from_account_info(acc_info)?, info: acc_info.clone(),
}) account: val,
}),
Err(_) => Err(ErrorCode::AccountSysvarMismatch.into()),
}
} }
} }

View File

@ -152,6 +152,9 @@ pub enum ErrorCode {
/// 3014 - The given account is not the associated token account /// 3014 - The given account is not the associated token account
#[msg("The given account is not the associated token account")] #[msg("The given account is not the associated token account")]
AccountNotAssociatedTokenAccount, AccountNotAssociatedTokenAccount,
/// 3015 - The given public key does not match the required sysvar
#[msg("The given public key does not match the required sysvar")]
AccountSysvarMismatch,
// State. // State.
/// 4000 - The given state account does not have the correct address /// 4000 - The given state account does not have the correct address

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-syn" name = "anchor-syn"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
repository = "https://github.com/project-serum/anchor" repository = "https://github.com/project-serum/anchor"
license = "Apache-2.0" license = "Apache-2.0"

View File

@ -22,7 +22,8 @@ pub fn generate(accs: &AccountsStruct) -> proc_macro2::TokenStream {
AccountField::CompositeField(s) => { AccountField::CompositeField(s) => {
let name = &s.ident; let name = &s.ident;
let docs = if !s.docs.is_empty() { let docs = if !s.docs.is_empty() {
proc_macro2::TokenStream::from_str(&format!("#[doc = \"{}\"]", s.docs)).unwrap() proc_macro2::TokenStream::from_str(&format!("#[doc = r#\"{}\"#]", s.docs))
.unwrap()
} else { } else {
quote!() quote!()
}; };
@ -41,7 +42,8 @@ pub fn generate(accs: &AccountsStruct) -> proc_macro2::TokenStream {
AccountField::Field(f) => { AccountField::Field(f) => {
let name = &f.ident; let name = &f.ident;
let docs = if !f.docs.is_empty() { let docs = if !f.docs.is_empty() {
proc_macro2::TokenStream::from_str(&format!("#[doc = \"{}\"]", f.docs)).unwrap() proc_macro2::TokenStream::from_str(&format!("#[doc = r#\"{}\"#]", f.docs))
.unwrap()
} else { } else {
quote!() quote!()
}; };

View File

@ -23,7 +23,8 @@ pub fn generate(accs: &AccountsStruct) -> proc_macro2::TokenStream {
AccountField::CompositeField(s) => { AccountField::CompositeField(s) => {
let name = &s.ident; let name = &s.ident;
let docs = if !s.docs.is_empty() { let docs = if !s.docs.is_empty() {
proc_macro2::TokenStream::from_str(&format!("#[doc = \"{}\"]", s.docs)).unwrap() proc_macro2::TokenStream::from_str(&format!("#[doc = r#\"{}\"#]", s.docs))
.unwrap()
} else { } else {
quote!() quote!()
}; };
@ -42,7 +43,8 @@ pub fn generate(accs: &AccountsStruct) -> proc_macro2::TokenStream {
AccountField::Field(f) => { AccountField::Field(f) => {
let name = &f.ident; let name = &f.ident;
let docs = if !f.docs.is_empty() { let docs = if !f.docs.is_empty() {
proc_macro2::TokenStream::from_str(&format!("#[doc = \"{}\"]", f.docs)).unwrap() proc_macro2::TokenStream::from_str(&format!("#[doc = r#\"{}\"#]", f.docs))
.unwrap()
} else { } else {
quote!() quote!()
}; };

View File

@ -480,29 +480,7 @@ fn generate_constraint_init_group(f: &Field, c: &ConstraintInitGroup) -> proc_ma
} }
InitKind::Program { owner } => { InitKind::Program { owner } => {
// Define the space variable. // Define the space variable.
let space = match space { let space = quote! {let space = #space;};
// If no explicit space param was given, serialize the type to bytes
// and take the length (with +8 for the discriminator.)
None => {
let account_ty = f.account_ty();
match matches!(f.ty, Ty::Loader(_) | Ty::AccountLoader(_)) {
false => {
quote! {
let space = 8 + #account_ty::default().try_to_vec().unwrap().len();
}
}
true => {
quote! {
let space = 8 + anchor_lang::__private::bytemuck::bytes_of(&#account_ty::default()).len();
}
}
}
}
// Explicit account size given. Use it.
Some(s) => quote! {
let space = #s;
},
};
// Define the owner of the account being created. If not specified, // Define the owner of the account being created. If not specified,
// default to the currently executing program. // default to the currently executing program.

View File

@ -353,7 +353,7 @@ fn parse_account_derives(ctx: &CrateContext) -> HashMap<String, AccountsStruct>
ctx.structs() ctx.structs()
.filter_map(|i_strct| { .filter_map(|i_strct| {
for attr in &i_strct.attrs { for attr in &i_strct.attrs {
if attr.tokens.to_string().contains(DERIVE_NAME) { if attr.path.is_ident("derive") && attr.tokens.to_string().contains(DERIVE_NAME) {
let strct = accounts::parse(i_strct).expect("Code not parseable"); let strct = accounts::parse(i_strct).expect("Code not parseable");
return Some((strct.ident.to_string(), strct)); return Some((strct.ident.to_string(), strct));
} }

View File

@ -721,7 +721,7 @@ pub enum ConstraintRentExempt {
pub struct ConstraintInitGroup { pub struct ConstraintInitGroup {
pub if_needed: bool, pub if_needed: bool,
pub seeds: Option<ConstraintSeedsGroup>, pub seeds: Option<ConstraintSeedsGroup>,
pub payer: Option<Expr>, pub payer: Expr,
pub space: Option<Expr>, pub space: Option<Expr>,
pub kind: InitKind, pub kind: InitKind,
} }

View File

@ -505,17 +505,28 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
} }
} }
// SPL Space. // Space.
if self.init.is_some() if let Some(i) = &self.init {
&& self.seeds.is_some() let initializing_token_program_acc = self.token_mint.is_some()
&& self.token_mint.is_some() || self.mint_authority.is_some()
&& (self.mint_authority.is_some() || self.token_authority.is_some()) || self.token_authority.is_some()
&& self.space.is_some() || self.associated_token_authority.is_some();
{
return Err(ParseError::new( match (self.space.is_some(), initializing_token_program_acc) {
self.space.as_ref().unwrap().span(), (true, true) => {
"space is not required for initializing an spl account", return Err(ParseError::new(
)); self.space.as_ref().unwrap().span(),
"space is not required for initializing an spl account",
));
}
(false, false) => {
return Err(ParseError::new(
i.span(),
"space must be provided with init",
));
}
_ => (),
}
} }
let ConstraintGroupBuilder { let ConstraintGroupBuilder {
@ -593,7 +604,7 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
init: init.as_ref().map(|i| Ok(ConstraintInitGroup { init: init.as_ref().map(|i| Ok(ConstraintInitGroup {
if_needed: i.if_needed, if_needed: i.if_needed,
seeds: seeds.clone(), seeds: seeds.clone(),
payer: into_inner!(payer.clone()).map(|a| a.target), payer: into_inner!(payer.clone()).unwrap().target,
space: space.clone().map(|s| s.space.clone()), space: space.clone().map(|s| s.space.clone()),
kind: if let Some(tm) = &token_mint { kind: if let Some(tm) = &token_mint {
InitKind::Token { InitKind::Token {

View File

@ -93,8 +93,7 @@ fn constraints_cross_checks(fields: &[AccountField]) -> ParseResult<()> {
for field in init_fields { for field in init_fields {
// Get payer for init-ed account // Get payer for init-ed account
let associated_payer_name = match field.constraints.init.clone().unwrap().payer.unwrap() let associated_payer_name = match field.constraints.init.clone().unwrap().payer {
{
// composite payer, check not supported // composite payer, check not supported
Expr::Field(_) => continue, Expr::Field(_) => continue,
field_name => field_name.to_token_stream().to_string(), field_name => field_name.to_token_stream().to_string(),

View File

@ -1,6 +1,6 @@
[package] [package]
name = "anchor-spl" name = "anchor-spl"
version = "0.22.0" version = "0.22.1"
authors = ["Serum Foundation <foundation@projectserum.com>"] authors = ["Serum Foundation <foundation@projectserum.com>"]
edition = "2018" edition = "2018"
license = "Apache-2.0" license = "Apache-2.0"
@ -17,7 +17,7 @@ devnet = []
dex = ["serum_dex"] dex = ["serum_dex"]
[dependencies] [dependencies]
anchor-lang = { path = "../lang", version = "0.22.0", features = ["derive"] } anchor-lang = { path = "../lang", version = "0.22.1", features = ["derive"] }
serum_dex = { git = "https://github.com/project-serum/serum-dex", rev = "1be91f2", version = "0.4.0", features = ["no-entrypoint"], optional = true } serum_dex = { git = "https://github.com/project-serum/serum-dex", rev = "1be91f2", version = "0.4.0", features = ["no-entrypoint"], optional = true }
solana-program = "1.8.5" solana-program = "1.8.5"
spl-token = { version = "3.1.1", features = ["no-entrypoint"], optional = true } spl-token = { version = "3.1.1", features = ["no-entrypoint"], optional = true }

View File

@ -1,11 +1,11 @@
use anchor_lang::solana_program::account_info::AccountInfo; use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::entrypoint::ProgramResult;
use anchor_lang::solana_program::pubkey::Pubkey; use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts}; use anchor_lang::{context::CpiContext, Accounts};
pub use spl_associated_token_account::{get_associated_token_address, ID}; pub use spl_associated_token_account::{get_associated_token_address, ID};
pub fn create<'info>(ctx: CpiContext<'_, '_, '_, 'info, Create<'info>>) -> ProgramResult { pub fn create<'info>(ctx: CpiContext<'_, '_, '_, 'info, Create<'info>>) -> Result<()> {
let ix = spl_associated_token_account::create_associated_token_account( let ix = spl_associated_token_account::create_associated_token_account(
ctx.accounts.payer.key, ctx.accounts.payer.key,
ctx.accounts.authority.key, ctx.accounts.authority.key,
@ -24,6 +24,7 @@ pub fn create<'info>(ctx: CpiContext<'_, '_, '_, 'info, Create<'info>>) -> Progr
], ],
ctx.signer_seeds, ctx.signer_seeds,
) )
.map_err(Into::into)
} }
#[derive(Accounts)] #[derive(Accounts)]

View File

@ -104,6 +104,21 @@ pub fn approve<'a, 'b, 'c, 'info>(
.map_err(Into::into) .map_err(Into::into)
} }
pub fn revoke<'a, 'b, 'c, 'info>(ctx: CpiContext<'a, 'b, 'c, 'info, Revoke<'info>>) -> Result<()> {
let ix = spl_token::instruction::revoke(
&spl_token::ID,
ctx.accounts.source.key,
ctx.accounts.authority.key,
&[],
)?;
solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.source.clone(), ctx.accounts.authority.clone()],
ctx.signer_seeds,
)
.map_err(Into::into)
}
pub fn initialize_account<'a, 'b, 'c, 'info>( pub fn initialize_account<'a, 'b, 'c, 'info>(
ctx: CpiContext<'a, 'b, 'c, 'info, InitializeAccount<'info>>, ctx: CpiContext<'a, 'b, 'c, 'info, InitializeAccount<'info>>,
) -> Result<()> { ) -> Result<()> {
@ -270,6 +285,12 @@ pub struct Approve<'info> {
pub authority: AccountInfo<'info>, pub authority: AccountInfo<'info>,
} }
#[derive(Accounts)]
pub struct Revoke<'info> {
pub source: AccountInfo<'info>,
pub authority: AccountInfo<'info>,
}
#[derive(Accounts)] #[derive(Accounts)]
pub struct InitializeAccount<'info> { pub struct InitializeAccount<'info> {
pub account: AccountInfo<'info>, pub account: AccountInfo<'info>,

View File

@ -1,6 +1,6 @@
{ {
"dependencies": { "dependencies": {
"@project-serum/anchor": "^0.22.0" "@project-serum/anchor": "^0.22.1"
}, },
"devDependencies": { "devDependencies": {
"chai": "^4.3.4", "chai": "^4.3.4",

View File

@ -32,11 +32,14 @@ pub mod bpf_upgradeable_state {
} }
#[account] #[account]
#[derive(Default, Debug)]
pub struct Settings { pub struct Settings {
admin_data: u64, admin_data: u64,
} }
impl Settings {
pub const LEN: usize = 8;
}
#[error_code] #[error_code]
pub enum CustomError { pub enum CustomError {
InvalidProgramDataAddress, InvalidProgramDataAddress,
@ -49,7 +52,7 @@ pub struct SetAdminSettings<'info> {
// In a real program, this should be a PDA, // In a real program, this should be a PDA,
// so the authority cannot create multiple settings accounts. // so the authority cannot create multiple settings accounts.
// Not done here for easier testing // Not done here for easier testing
#[account(init, payer = authority)] #[account(init, payer = authority, space = Settings::LEN + 8)]
pub settings: Account<'info, Settings>, pub settings: Account<'info, Settings>,
#[account(mut)] #[account(mut)]
pub authority: Signer<'info>, pub authority: Signer<'info>,
@ -65,7 +68,7 @@ pub struct SetAdminSettingsUseProgramState<'info> {
// In a real program, this should be a PDA, // In a real program, this should be a PDA,
// so the authority cannot create multiple settings accounts. // so the authority cannot create multiple settings accounts.
// Not done here for easier testing // Not done here for easier testing
#[account(init, payer = authority)] #[account(init, payer = authority, space = Settings::LEN + 8)]
pub settings: Account<'info, Settings>, pub settings: Account<'info, Settings>,
#[account(mut)] #[account(mut)]
pub authority: Signer<'info>, pub authority: Signer<'info>,

View File

@ -1,6 +1,6 @@
{ {
"name": "cashiers-check", "name": "cashiers-check",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "cfo", "name": "cfo",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -195,7 +195,7 @@ pub mod cfo {
let expiry_ts = 1853942400; // 9/30/2028. let expiry_ts = 1853942400; // 9/30/2028.
let expiry_receiver = *ctx.accounts.officer.to_account_info().key; let expiry_receiver = *ctx.accounts.officer.to_account_info().key;
let locked_kind = { let locked_kind = {
let start_ts = 1633017600; // 9/30.22.0. let start_ts = 1633017600; // 9/30.22.1.
let end_ts = 1822320000; // 9/30/2027. let end_ts = 1822320000; // 9/30/2027.
let period_count = 2191; let period_count = 2191;
RewardVendorKind::Locked { RewardVendorKind::Locked {
@ -324,6 +324,7 @@ pub struct CreateOfficer<'info> {
seeds = [dex_program.key.as_ref()], seeds = [dex_program.key.as_ref()],
bump, bump,
payer = authority, payer = authority,
space = Officer::LEN + 8
)] )]
officer: Box<Account<'info, Officer>>, officer: Box<Account<'info, Officer>>,
#[account( #[account(
@ -332,7 +333,7 @@ pub struct CreateOfficer<'info> {
bump, bump,
payer = authority, payer = authority,
token::mint = srm_mint, token::mint = srm_mint,
token::authority = officer, token::authority = officer
)] )]
srm_vault: Box<Account<'info, TokenAccount>>, srm_vault: Box<Account<'info, TokenAccount>>,
#[account( #[account(
@ -341,7 +342,7 @@ pub struct CreateOfficer<'info> {
bump, bump,
payer = authority, payer = authority,
token::mint = usdc_mint, token::mint = usdc_mint,
token::authority = officer, token::authority = officer
)] )]
usdc_vault: Box<Account<'info, TokenAccount>>, usdc_vault: Box<Account<'info, TokenAccount>>,
#[account( #[account(
@ -350,7 +351,7 @@ pub struct CreateOfficer<'info> {
bump, bump,
payer = authority, payer = authority,
token::mint = srm_mint, token::mint = srm_mint,
token::authority = officer, token::authority = officer
)] )]
stake: Box<Account<'info, TokenAccount>>, stake: Box<Account<'info, TokenAccount>>,
#[account( #[account(
@ -359,7 +360,7 @@ pub struct CreateOfficer<'info> {
bump, bump,
payer = authority, payer = authority,
token::mint = srm_mint, token::mint = srm_mint,
token::authority = officer, token::authority = officer
)] )]
treasury: Box<Account<'info, TokenAccount>>, treasury: Box<Account<'info, TokenAccount>>,
#[account(mut)] #[account(mut)]
@ -392,6 +393,7 @@ pub struct AuthorizeMarket<'info> {
payer = payer, payer = payer,
seeds = [b"market-auth", officer.key().as_ref(), market.key.as_ref()], seeds = [b"market-auth", officer.key().as_ref(), market.key.as_ref()],
bump, bump,
space = MarketAuth::LEN + 8
)] )]
market_auth: Account<'info, MarketAuth>, market_auth: Account<'info, MarketAuth>,
#[account(mut)] #[account(mut)]
@ -421,7 +423,7 @@ pub struct CreateOfficerToken<'info> {
bump, bump,
token::mint = mint, token::mint = mint,
token::authority = officer, token::authority = officer,
payer = payer, payer = payer
)] )]
token: Account<'info, TokenAccount>, token: Account<'info, TokenAccount>,
mint: Account<'info, Mint>, mint: Account<'info, Mint>,
@ -666,28 +668,31 @@ pub struct DropStakeRewardPool<'info> {
/// ///
/// PDA - [dex_program_id]. /// PDA - [dex_program_id].
#[account] #[account]
#[derive(Default)]
pub struct Officer { pub struct Officer {
// Priviledged account. // Priviledged account.
pub authority: Pubkey, pub authority: Pubkey, // 32
// Vault holding the officer's SRM tokens prior to distribution. // Vault holding the officer's SRM tokens prior to distribution.
pub srm_vault: Pubkey, pub srm_vault: Pubkey, // 32
// Escrow SRM vault holding tokens which are dropped onto stakers. // Escrow SRM vault holding tokens which are dropped onto stakers.
pub stake: Pubkey, pub stake: Pubkey, // 32
// SRM token account to send treasury earned tokens to. // SRM token account to send treasury earned tokens to.
pub treasury: Pubkey, pub treasury: Pubkey, // 32
// Defines the fee distribution, i.e., what percent each fee category gets. // Defines the fee distribution, i.e., what percent each fee category gets.
pub distribution: Distribution, pub distribution: Distribution, // Distribution::LEN
// Swap frontend for the dex. // Swap frontend for the dex.
pub swap_program: Pubkey, pub swap_program: Pubkey, // 32
// Dex program the officer is associated with. // Dex program the officer is associated with.
pub dex_program: Pubkey, pub dex_program: Pubkey, // 32
// SRM stake pool address // SRM stake pool address
pub registrar: Pubkey, pub registrar: Pubkey, // 32
// MSRM stake pool address. // MSRM stake pool address.
pub msrm_registrar: Pubkey, pub msrm_registrar: Pubkey, // 32
// Bump seeds for pdas. // Bump seeds for pdas.
pub bumps: OfficerBumps, pub bumps: OfficerBumps, // OfficerBumps::LEN
}
impl Officer {
pub const LEN: usize = 8 * 32 + Distribution::LEN + OfficerBumps::LEN;
} }
/// MarketAuth represents an authorization token created by the Officer /// MarketAuth represents an authorization token created by the Officer
@ -702,26 +707,37 @@ pub struct Officer {
/// ///
/// PDA - [b"market-auth", officer, market_address] /// PDA - [b"market-auth", officer, market_address]
#[account] #[account]
#[derive(Default)]
pub struct MarketAuth { pub struct MarketAuth {
// Bump seed for this account's PDA. // Bump seed for this account's PDA.
pub bump: u8, pub bump: u8, // 1
}
impl MarketAuth {
pub const LEN: usize = 1;
} }
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)] #[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)]
pub struct OfficerBumps { pub struct OfficerBumps {
pub bump: u8, pub bump: u8, // 1
pub srm: u8, pub srm: u8, // 1
pub usdc: u8, pub usdc: u8, // 1
pub stake: u8, pub stake: u8, // 1
pub treasury: u8, pub treasury: u8, // 1
}
impl OfficerBumps {
pub const LEN: usize = 5;
} }
#[derive(AnchorSerialize, AnchorDeserialize, Default, Clone)] #[derive(AnchorSerialize, AnchorDeserialize, Default, Clone)]
pub struct Distribution { pub struct Distribution {
burn: u8, burn: u8, // 1
stake: u8, stake: u8, // 1
treasury: u8, treasury: u8, // 1
}
impl Distribution {
pub const LEN: usize = 3;
} }
// CpiContext transformations. // CpiContext transformations.

View File

@ -1,6 +1,6 @@
{ {
"name": "chat", "name": "chat",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "composite", "name": "composite",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "declare-id", "name": "declare-id",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "errors", "name": "errors",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -24,6 +24,7 @@ pub struct Hello<'info> {
pub rent: Sysvar<'info, Rent>, pub rent: Sysvar<'info, Rent>,
/// Composite accounts test. /// Composite accounts test.
/// Multiple lines supported. /// Multiple lines supported.
/// You can also include "double quotes".
pub other: HelloComposite<'info>, pub other: HelloComposite<'info>,
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "errors", "name": "errors",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "escrow", "name": "escrow",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "events", "name": "events",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "floats", "name": "floats",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "ido-pool", "name": "ido-pool",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -295,7 +295,9 @@ pub struct InitializePool<'info> {
#[account(init, #[account(init,
seeds = [ido_name.as_bytes()], seeds = [ido_name.as_bytes()],
bump, bump,
payer = ido_authority)] payer = ido_authority,
space = IdoAccount::LEN + 8
)]
pub ido_account: Box<Account<'info, IdoAccount>>, pub ido_account: Box<Account<'info, IdoAccount>>,
// TODO Confirm USDC mint address on mainnet or leave open as an option for other stables // TODO Confirm USDC mint address on mainnet or leave open as an option for other stables
#[account(constraint = usdc_mint.decimals == DECIMALS)] #[account(constraint = usdc_mint.decimals == DECIMALS)]
@ -305,7 +307,8 @@ pub struct InitializePool<'info> {
mint::authority = ido_account, mint::authority = ido_account,
seeds = [ido_name.as_bytes(), b"redeemable_mint".as_ref()], seeds = [ido_name.as_bytes(), b"redeemable_mint".as_ref()],
bump, bump,
payer = ido_authority)] payer = ido_authority
)]
pub redeemable_mint: Box<Account<'info, Mint>>, pub redeemable_mint: Box<Account<'info, Mint>>,
#[account(constraint = watermelon_mint.key() == ido_authority_watermelon.mint)] #[account(constraint = watermelon_mint.key() == ido_authority_watermelon.mint)]
pub watermelon_mint: Box<Account<'info, Mint>>, pub watermelon_mint: Box<Account<'info, Mint>>,
@ -314,14 +317,16 @@ pub struct InitializePool<'info> {
token::authority = ido_account, token::authority = ido_account,
seeds = [ido_name.as_bytes(), b"pool_watermelon"], seeds = [ido_name.as_bytes(), b"pool_watermelon"],
bump, bump,
payer = ido_authority)] payer = ido_authority
)]
pub pool_watermelon: Box<Account<'info, TokenAccount>>, pub pool_watermelon: Box<Account<'info, TokenAccount>>,
#[account(init, #[account(init,
token::mint = usdc_mint, token::mint = usdc_mint,
token::authority = ido_account, token::authority = ido_account,
seeds = [ido_name.as_bytes(), b"pool_usdc"], seeds = [ido_name.as_bytes(), b"pool_usdc"],
bump, bump,
payer = ido_authority)] payer = ido_authority
)]
pub pool_usdc: Box<Account<'info, TokenAccount>>, pub pool_usdc: Box<Account<'info, TokenAccount>>,
// Programs and Sysvars // Programs and Sysvars
pub system_program: Program<'info, System>, pub system_program: Program<'info, System>,
@ -341,7 +346,8 @@ pub struct InitUserRedeemable<'info> {
ido_account.ido_name.as_ref().trim_ascii_whitespace(), ido_account.ido_name.as_ref().trim_ascii_whitespace(),
b"user_redeemable"], b"user_redeemable"],
bump, bump,
payer = user_authority)] payer = user_authority
)]
pub user_redeemable: Box<Account<'info, TokenAccount>>, pub user_redeemable: Box<Account<'info, TokenAccount>>,
// IDO Accounts // IDO Accounts
#[account(seeds = [ido_account.ido_name.as_ref().trim_ascii_whitespace()], #[account(seeds = [ido_account.ido_name.as_ref().trim_ascii_whitespace()],
@ -401,7 +407,8 @@ pub struct InitEscrowUsdc<'info> {
ido_account.ido_name.as_ref().trim_ascii_whitespace(), ido_account.ido_name.as_ref().trim_ascii_whitespace(),
b"escrow_usdc"], b"escrow_usdc"],
bump, bump,
payer = user_authority)] payer = user_authority
)]
pub escrow_usdc: Box<Account<'info, TokenAccount>>, pub escrow_usdc: Box<Account<'info, TokenAccount>>,
#[account(seeds = [ido_account.ido_name.as_ref().trim_ascii_whitespace()], #[account(seeds = [ido_account.ido_name.as_ref().trim_ascii_whitespace()],
bump = ido_account.bumps.ido_account, bump = ido_account.bumps.ido_account,
@ -541,36 +548,39 @@ pub struct WithdrawFromEscrow<'info> {
} }
#[account] #[account]
#[derive(Default)]
pub struct IdoAccount { pub struct IdoAccount {
pub ido_name: [u8; 10], // Setting an arbitrary max of ten characters in the ido name. pub ido_name: [u8; 10], // Setting an arbitrary max of ten characters in the ido name. // 10
pub bumps: PoolBumps, pub bumps: PoolBumps, // 4
pub ido_authority: Pubkey, pub ido_authority: Pubkey, // 32
pub usdc_mint: Pubkey, pub usdc_mint: Pubkey, // 32
pub redeemable_mint: Pubkey, pub redeemable_mint: Pubkey, // 32
pub watermelon_mint: Pubkey, pub watermelon_mint: Pubkey, // 32
pub pool_usdc: Pubkey, pub pool_usdc: Pubkey, // 32
pub pool_watermelon: Pubkey, pub pool_watermelon: Pubkey, // 32
pub num_ido_tokens: u64, pub num_ido_tokens: u64, // 8
pub ido_times: IdoTimes, pub ido_times: IdoTimes, // 32
}
impl IdoAccount {
pub const LEN: usize = 10 + 4 + 32 + 5 * 32 + 8 + 32;
} }
#[derive(AnchorSerialize, AnchorDeserialize, Default, Clone, Copy)] #[derive(AnchorSerialize, AnchorDeserialize, Default, Clone, Copy)]
pub struct IdoTimes { pub struct IdoTimes {
pub start_ido: i64, pub start_ido: i64, // 8
pub end_deposits: i64, pub end_deposits: i64, // 8
pub end_ido: i64, pub end_ido: i64, // 8
pub end_escrow: i64, pub end_escrow: i64, // 8
} }
#[derive(AnchorSerialize, AnchorDeserialize, Default, Clone)] #[derive(AnchorSerialize, AnchorDeserialize, Default, Clone)]
pub struct PoolBumps { pub struct PoolBumps {
pub ido_account: u8, pub ido_account: u8, // 1
pub redeemable_mint: u8, pub redeemable_mint: u8, // 1
pub pool_watermelon: u8, pub pool_watermelon: u8, // 1
pub pool_usdc: u8, pub pool_usdc: u8, // 1
} }
#[error_code] #[error_code]

View File

@ -1,6 +1,6 @@
{ {
"name": "interface", "name": "interface",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "lockup", "name": "lockup",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "misc", "name": "misc",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,50 +1,63 @@
use anchor_lang::prelude::*; use anchor_lang::prelude::*;
macro_rules! size {
($name: ident, $size:expr) => {
impl $name {
pub const LEN: usize = $size;
}
};
}
pub const MAX_SIZE: usize = 10; pub const MAX_SIZE: usize = 10;
#[account] #[account]
pub struct Data { pub struct Data {
pub udata: u128, pub udata: u128, // 16
pub idata: i128, pub idata: i128, // 16
} }
size!(Data, 32);
#[account] #[account]
#[derive(Default)]
pub struct DataU16 { pub struct DataU16 {
pub data: u16, pub data: u16, // 2
} }
size!(DataU16, 32);
#[account] #[account]
#[derive(Default)]
pub struct DataI8 { pub struct DataI8 {
pub data: i8, pub data: i8, // 1
} }
size!(DataI8, 1);
#[account] #[account]
pub struct DataI16 { pub struct DataI16 {
pub data: i16, pub data: i16, // 2
} }
size!(DataI16, 2);
#[account(zero_copy)] #[account(zero_copy)]
#[derive(Default)]
pub struct DataZeroCopy { pub struct DataZeroCopy {
pub data: u16, pub data: u16, // 2
pub bump: u8, pub _padding: u8, // 1
pub bump: u8, // 1
} }
size!(DataZeroCopy, 4);
#[account] #[account]
#[derive(Default)]
pub struct DataWithFilter { pub struct DataWithFilter {
pub authority: Pubkey, pub authority: Pubkey, // 32
pub filterable: Pubkey, pub filterable: Pubkey, // 32
} }
size!(DataWithFilter, 64);
#[account] #[account]
pub struct DataMultidimensionalArray { pub struct DataMultidimensionalArray {
pub data: [[u8; 10]; 10], pub data: [[u8; 10]; 10], // 100
} }
size!(DataMultidimensionalArray, 100);
#[account] #[account]
pub struct DataConstArraySize { pub struct DataConstArraySize {
pub data: [u8; MAX_SIZE], pub data: [u8; MAX_SIZE], // 10
} }
size!(DataConstArraySize, MAX_SIZE);

View File

@ -16,15 +16,17 @@ pub struct TestTokenSeedsInit<'info> {
payer = authority, payer = authority,
mint::decimals = 6, mint::decimals = 6,
mint::authority = authority, mint::authority = authority,
)] )]
pub mint: Account<'info, Mint>, pub mint: Account<'info, Mint>,
#[account( #[account(
init, init,
seeds = [b"my-token-seed".as_ref(),], seeds = [b"my-token-seed".as_ref()],
bump, bump,
payer = authority, payer = authority,
token::mint = mint, token::mint = mint,
token::authority = authority, token::authority = authority,
)] )]
pub my_pda: Account<'info, TokenAccount>, pub my_pda: Account<'info, TokenAccount>,
#[account(mut)] #[account(mut)]
@ -42,6 +44,7 @@ pub struct TestInitAssociatedToken<'info> {
payer = payer, payer = payer,
associated_token::mint = mint, associated_token::mint = mint,
associated_token::authority = payer, associated_token::authority = payer,
)] )]
pub token: Account<'info, TokenAccount>, pub token: Account<'info, TokenAccount>,
pub mint: Account<'info, Mint>, pub mint: Account<'info, Mint>,
@ -86,6 +89,7 @@ pub struct TestPdaInit<'info> {
seeds = [b"my-seed", domain.as_bytes(), foo.key.as_ref(), &seed], seeds = [b"my-seed", domain.as_bytes(), foo.key.as_ref(), &seed],
bump, bump,
payer = my_payer, payer = my_payer,
space = DataU16::LEN + 8
)] )]
pub my_pda: Account<'info, DataU16>, pub my_pda: Account<'info, DataU16>,
#[account(mut)] #[account(mut)]
@ -102,8 +106,9 @@ pub struct TestPdaInitZeroCopy<'info> {
seeds = [b"my-seed".as_ref()], seeds = [b"my-seed".as_ref()],
bump, bump,
payer = my_payer, payer = my_payer,
space = DataZeroCopy::LEN + 8
)] )]
pub my_pda: Loader<'info, DataZeroCopy>, pub my_pda: AccountLoader<'info, DataZeroCopy>,
#[account(mut)] #[account(mut)]
pub my_payer: Signer<'info>, pub my_payer: Signer<'info>,
pub system_program: Program<'info, System>, pub system_program: Program<'info, System>,
@ -116,7 +121,7 @@ pub struct TestPdaMutZeroCopy<'info> {
seeds = [b"my-seed".as_ref()], seeds = [b"my-seed".as_ref()],
bump = my_pda.load()?.bump, bump = my_pda.load()?.bump,
)] )]
pub my_pda: Loader<'info, DataZeroCopy>, pub my_pda: AccountLoader<'info, DataZeroCopy>,
/// CHECK: /// CHECK:
pub my_payer: AccountInfo<'info>, pub my_payer: AccountInfo<'info>,
} }
@ -204,7 +209,7 @@ pub struct TestI8<'info> {
#[derive(Accounts)] #[derive(Accounts)]
pub struct TestInit<'info> { pub struct TestInit<'info> {
#[account(init, payer = payer)] #[account(init, payer = payer, space = DataI8::LEN + 8)]
pub data: Account<'info, DataI8>, pub data: Account<'info, DataI8>,
#[account(mut)] #[account(mut)]
pub payer: Signer<'info>, pub payer: Signer<'info>,
@ -213,7 +218,7 @@ pub struct TestInit<'info> {
#[derive(Accounts)] #[derive(Accounts)]
pub struct TestInitZeroCopy<'info> { pub struct TestInitZeroCopy<'info> {
#[account(init, payer = payer, space = 8 + size_of::<DataZeroCopy>())] #[account(init, payer = payer, space = DataZeroCopy::LEN + 8)]
pub data: Loader<'info, DataZeroCopy>, pub data: Loader<'info, DataZeroCopy>,
#[account(mut)] #[account(mut)]
pub payer: Signer<'info>, pub payer: Signer<'info>,
@ -222,7 +227,7 @@ pub struct TestInitZeroCopy<'info> {
#[derive(Accounts)] #[derive(Accounts)]
pub struct TestInitMint<'info> { pub struct TestInitMint<'info> {
#[account(init, mint::decimals = 6, mint::authority = payer, mint::freeze_authority = payer, payer = payer)] #[account(init, mint::decimals = 6, mint::authority = payer, mint::freeze_authority = payer, payer = payer, )]
pub mint: Account<'info, Mint>, pub mint: Account<'info, Mint>,
#[account(mut)] #[account(mut)]
pub payer: Signer<'info>, pub payer: Signer<'info>,
@ -233,7 +238,7 @@ pub struct TestInitMint<'info> {
#[derive(Accounts)] #[derive(Accounts)]
pub struct TestInitToken<'info> { pub struct TestInitToken<'info> {
#[account(init, token::mint = mint, token::authority = payer, payer = payer)] #[account(init, token::mint = mint, token::authority = payer, payer = payer, )]
pub token: Account<'info, TokenAccount>, pub token: Account<'info, TokenAccount>,
pub mint: Account<'info, Mint>, pub mint: Account<'info, Mint>,
#[account(mut)] #[account(mut)]
@ -246,14 +251,14 @@ pub struct TestInitToken<'info> {
#[derive(Accounts)] #[derive(Accounts)]
pub struct TestCompositePayer<'info> { pub struct TestCompositePayer<'info> {
pub composite: TestInit<'info>, pub composite: TestInit<'info>,
#[account(init, payer = composite.payer, space = 8 + size_of::<Data>())] #[account(init, payer = composite.payer, space = Data::LEN + 8)]
pub data: Account<'info, Data>, pub data: Account<'info, Data>,
pub system_program: Program<'info, System>, pub system_program: Program<'info, System>,
} }
#[derive(Accounts)] #[derive(Accounts)]
pub struct TestFetchAll<'info> { pub struct TestFetchAll<'info> {
#[account(init, payer = authority)] #[account(init, payer = authority, space = DataWithFilter::LEN + 8)]
pub data: Account<'info, DataWithFilter>, pub data: Account<'info, DataWithFilter>,
#[account(mut)] #[account(mut)]
pub authority: Signer<'info>, pub authority: Signer<'info>,
@ -262,7 +267,7 @@ pub struct TestFetchAll<'info> {
#[derive(Accounts)] #[derive(Accounts)]
pub struct TestInitWithEmptySeeds<'info> { pub struct TestInitWithEmptySeeds<'info> {
#[account(init, seeds = [], bump, payer = authority, space = 8 + size_of::<Data>())] #[account(init, seeds = [], bump, payer = authority, space = Data::LEN + 8)]
pub pda: Account<'info, Data>, pub pda: Account<'info, Data>,
#[account(mut)] #[account(mut)]
pub authority: Signer<'info>, pub authority: Signer<'info>,
@ -278,7 +283,7 @@ pub struct TestEmptySeedsConstraint<'info> {
#[derive(Accounts)] #[derive(Accounts)]
pub struct InitWithSpace<'info> { pub struct InitWithSpace<'info> {
#[account(init, payer = payer)] #[account(init, payer = payer, space = DataU16::LEN + 8)]
pub data: Account<'info, DataU16>, pub data: Account<'info, DataU16>,
#[account(mut)] #[account(mut)]
pub payer: Signer<'info>, pub payer: Signer<'info>,
@ -287,7 +292,8 @@ pub struct InitWithSpace<'info> {
#[derive(Accounts)] #[derive(Accounts)]
pub struct TestInitIfNeeded<'info> { pub struct TestInitIfNeeded<'info> {
#[account(init_if_needed, payer = payer, space = 500)] // intentionally using more space (+500) to check whether space is checked when using init_if_needed
#[account(init_if_needed, payer = payer, space = DataU16::LEN + 8 + 500)]
pub data: Account<'info, DataU16>, pub data: Account<'info, DataU16>,
#[account(mut)] #[account(mut)]
pub payer: Signer<'info>, pub payer: Signer<'info>,
@ -335,7 +341,7 @@ pub struct TestInitMintIfNeeded<'info> {
#[derive(Accounts)] #[derive(Accounts)]
pub struct TestInitTokenIfNeeded<'info> { pub struct TestInitTokenIfNeeded<'info> {
#[account(init_if_needed, token::mint = mint, token::authority = authority, payer = payer)] #[account(init_if_needed, token::mint = mint, token::authority = authority, payer = payer, )]
pub token: Account<'info, TokenAccount>, pub token: Account<'info, TokenAccount>,
pub mint: Account<'info, Mint>, pub mint: Account<'info, Mint>,
#[account(mut)] #[account(mut)]
@ -353,7 +359,7 @@ pub struct TestInitAssociatedTokenIfNeeded<'info> {
init_if_needed, init_if_needed,
payer = payer, payer = payer,
associated_token::mint = mint, associated_token::mint = mint,
associated_token::authority = authority, associated_token::authority = authority
)] )]
pub token: Account<'info, TokenAccount>, pub token: Account<'info, TokenAccount>,
pub mint: Account<'info, Mint>, pub mint: Account<'info, Mint>,

View File

@ -1002,7 +1002,8 @@ describe("misc", () => {
it("init_if_needed throws if account exists but is not the expected space", async () => { it("init_if_needed throws if account exists but is not the expected space", async () => {
const newAcc = anchor.web3.Keypair.generate(); const newAcc = anchor.web3.Keypair.generate();
await program.rpc.initWithSpace(3, { const _irrelevantForTest = 3;
await program.rpc.initWithSpace(_irrelevantForTest, {
accounts: { accounts: {
data: newAcc.publicKey, data: newAcc.publicKey,
systemProgram: anchor.web3.SystemProgram.programId, systemProgram: anchor.web3.SystemProgram.programId,
@ -1012,7 +1013,7 @@ describe("misc", () => {
}); });
try { try {
await program.rpc.testInitIfNeeded(3, { await program.rpc.testInitIfNeeded(_irrelevantForTest, {
accounts: { accounts: {
data: newAcc.publicKey, data: newAcc.publicKey,
systemProgram: anchor.web3.SystemProgram.programId, systemProgram: anchor.web3.SystemProgram.programId,

View File

@ -1,6 +1,6 @@
{ {
"name": "multisig", "name": "multisig",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -33,7 +33,7 @@
"declare-id" "declare-id"
], ],
"dependencies": { "dependencies": {
"@project-serum/anchor": "^0.22.0", "@project-serum/anchor": "^0.22.1",
"@project-serum/common": "^0.0.1-beta.3", "@project-serum/common": "^0.0.1-beta.3",
"@project-serum/serum": "^0.13.60", "@project-serum/serum": "^0.13.60",
"@solana/spl-token": "^0.1.8" "@solana/spl-token": "^0.1.8"

View File

@ -1,6 +1,6 @@
{ {
"name": "pda-derivation", "name": "pda-derivation",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "pyth", "name": "pyth",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -16,4 +16,4 @@ cpi = ["no-entrypoint"]
default = [] default = []
[dependencies] [dependencies]
anchor-lang = "0.22.0" anchor-lang = "0.22.1"

View File

@ -1,6 +1,6 @@
{ {
"name": "token-proxy", "name": "token-proxy",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "swap", "name": "swap",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "system-accounts", "name": "system-accounts",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "sysvars", "name": "sysvars",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,18 +1,39 @@
const anchor = require("@project-serum/anchor"); const anchor = require("@project-serum/anchor");
const assert = require("assert");
describe("sysvars", () => { describe("sysvars", () => {
// Configure the client to use the local cluster. // Configure the client to use the local cluster.
anchor.setProvider(anchor.Provider.local()); anchor.setProvider(anchor.Provider.local());
const program = anchor.workspace.Sysvars;
it("Is initialized!", async () => { it("Is initialized!", async () => {
const program = anchor.workspace.Sysvars; const tx = await program.methods
const tx = await program.rpc.sysvars({ .sysvars()
accounts: { .accounts({
clock: anchor.web3.SYSVAR_CLOCK_PUBKEY, clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
rent: anchor.web3.SYSVAR_RENT_PUBKEY, rent: anchor.web3.SYSVAR_RENT_PUBKEY,
stakeHistory: anchor.web3.SYSVAR_STAKE_HISTORY_PUBKEY, stakeHistory: anchor.web3.SYSVAR_STAKE_HISTORY_PUBKEY,
}, })
}); .rpc();
console.log("Your transaction signature", tx); console.log("Your transaction signature", tx);
}); });
it("Fails when the wrote pubkeys are provided", async () => {
try {
await program.methods
.sysvars()
.accounts({
clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
stakeHistory: anchor.web3.SYSVAR_REWARDS_PUBKEY,
})
.rpc();
assert.ok(false);
} catch (err) {
const errMsg = "The given public key does not match the required sysvar";
assert.strictEqual(err.toString(), errMsg);
assert.strictEqual(err.msg, errMsg);
assert.strictEqual(err.code, 3015);
}
});
}); });

View File

@ -1,6 +1,6 @@
{ {
"name": "tictactoe", "name": "tictactoe",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "typescript-example", "name": "typescript-example",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -1,6 +1,6 @@
{ {
"name": "zero-copy", "name": "zero-copy",
"version": "0.22.0", "version": "0.22.1",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/project-serum/anchor#readme", "homepage": "https://github.com/project-serum/anchor#readme",
"bugs": { "bugs": {

View File

@ -97,7 +97,8 @@ pub struct CreateBar<'info> {
init, init,
seeds = [authority.key().as_ref(), foo.key().as_ref()], seeds = [authority.key().as_ref(), foo.key().as_ref()],
bump, bump,
payer = authority, owner = *program_id payer = authority, owner = *program_id,
space = Bar::LEN + 8
)] )]
bar: AccountLoader<'info, Bar>, bar: AccountLoader<'info, Bar>,
#[account(mut)] #[account(mut)]
@ -132,8 +133,8 @@ pub struct UpdateLargeAccount<'info> {
} }
#[account(zero_copy)] #[account(zero_copy)]
#[derive(Default)]
#[repr(packed)] #[repr(packed)]
#[derive(Default)]
pub struct Foo { pub struct Foo {
pub authority: Pubkey, pub authority: Pubkey,
pub data: u64, pub data: u64,
@ -143,10 +144,13 @@ pub struct Foo {
} }
#[account(zero_copy)] #[account(zero_copy)]
#[derive(Default)]
pub struct Bar { pub struct Bar {
pub authority: Pubkey, pub authority: Pubkey, // 32
pub data: u64, pub data: u64, // 8
}
impl Bar {
pub const LEN: usize = 32 + 8;
} }
#[account(zero_copy)] #[account(zero_copy)]

View File

@ -1,6 +1,6 @@
{ {
"name": "@project-serum/anchor", "name": "@project-serum/anchor",
"version": "0.22.0", "version": "0.22.1",
"description": "Anchor client", "description": "Anchor client",
"module": "./dist/esm/index.js", "module": "./dist/esm/index.js",
"main": "./dist/cjs/index.js", "main": "./dist/cjs/index.js",

View File

@ -269,7 +269,8 @@ class InstructionFormatter {
? "null" ? "null"
: this.formatIdlData( : this.formatIdlData(
{ name: "", type: (<IdlTypeOption>idlField.type).option }, { name: "", type: (<IdlTypeOption>idlField.type).option },
data data,
types
); );
} }
if (idlField.type.hasOwnProperty("defined")) { if (idlField.type.hasOwnProperty("defined")) {

View File

@ -111,6 +111,7 @@ const LangErrorCode = {
AccountNotInitialized: 3012, AccountNotInitialized: 3012,
AccountNotProgramData: 3013, AccountNotProgramData: 3013,
AccountNotAssociatedTokenAccount: 3014, AccountNotAssociatedTokenAccount: 3014,
AccountSysvarMismatch: 3015,
// State. // State.
StateInvalidAddress: 4000, StateInvalidAddress: 4000,
@ -227,6 +228,10 @@ const LangErrorMessage = new Map([
LangErrorCode.AccountNotAssociatedTokenAccount, LangErrorCode.AccountNotAssociatedTokenAccount,
"The given account is not the associated token account", "The given account is not the associated token account",
], ],
[
LangErrorCode.AccountSysvarMismatch,
"The given public key does not match the required sysvar",
],
// State. // State.
[ [

View File

@ -10,6 +10,13 @@ import { coder } from "../spl/token";
// Populates a given accounts context with PDAs and common missing accounts. // Populates a given accounts context with PDAs and common missing accounts.
export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> { export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> {
static readonly CONST_ACCOUNTS = {
systemProgram: SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
associatedTokenProgram: ASSOCIATED_PROGRAM_ID,
rent: SYSVAR_RENT_PUBKEY,
};
private _accountStore: AccountStore<IDL>; private _accountStore: AccountStore<IDL>;
constructor( constructor(
@ -40,40 +47,28 @@ export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> {
const accountDescName = camelCase(accountDesc.name); const accountDescName = camelCase(accountDesc.name);
// PDA derived from IDL seeds. // PDA derived from IDL seeds.
if (accountDesc.pda && accountDesc.pda.seeds.length > 0) { if (
if (this._accounts[accountDescName] === undefined) { accountDesc.pda &&
await this.autoPopulatePda(accountDesc); accountDesc.pda.seeds.length > 0 &&
continue; !this._accounts[accountDescName]
} ) {
await this.autoPopulatePda(accountDesc);
continue;
} }
// Signers default to the provider. // Signers default to the provider.
if ( if (accountDesc.isSigner && !this._accounts[accountDescName]) {
accountDesc.isSigner &&
this._accounts[accountDescName] === undefined
) {
this._accounts[accountDescName] = this._provider.wallet.publicKey; this._accounts[accountDescName] = this._provider.wallet.publicKey;
continue; continue;
} }
// Common accounts are auto populated with magic names by convention. // Common accounts are auto populated with magic names by convention.
switch (accountDescName) { if (
case "systemProgram": Reflect.has(AccountsResolver.CONST_ACCOUNTS, accountDescName) &&
if (this._accounts[accountDescName] === undefined) { !this._accounts[accountDescName]
this._accounts[accountDescName] = SystemProgram.programId; ) {
} this._accounts[accountDescName] =
case "rent": AccountsResolver.CONST_ACCOUNTS[accountDescName];
if (this._accounts[accountDescName] === undefined) {
this._accounts[accountDescName] = SYSVAR_RENT_PUBKEY;
}
case "tokenProgram":
if (this._accounts[accountDescName] === undefined) {
this._accounts[accountDescName] = TOKEN_PROGRAM_ID;
}
case "associatedTokenProgram":
if (this._accounts[accountDescName] === undefined) {
this._accounts[accountDescName] = ASSOCIATED_PROGRAM_ID;
}
} }
} }
} }
@ -234,7 +229,7 @@ export class AccountStore<IDL extends Idl> {
publicKey: PublicKey publicKey: PublicKey
): Promise<T> { ): Promise<T> {
const address = publicKey.toString(); const address = publicKey.toString();
if (this._cache.get(address) === undefined) { if (!this._cache.has(address)) {
if (name === "TokenAccount") { if (name === "TokenAccount") {
const accountInfo = await this._provider.connection.getAccountInfo( const accountInfo = await this._provider.connection.getAccountInfo(
publicKey publicKey

View File

@ -77,6 +77,7 @@ export class Program<IDL extends Idl = Idl> {
* }, * },
* }); * });
* ``` * ```
* @deprecated
*/ */
readonly rpc: RpcNamespace<IDL>; readonly rpc: RpcNamespace<IDL>;
@ -130,6 +131,7 @@ export class Program<IDL extends Idl = Idl> {
* }, * },
* }); * });
* ``` * ```
* @deprecated
*/ */
readonly instruction: InstructionNamespace<IDL>; readonly instruction: InstructionNamespace<IDL>;
@ -161,6 +163,7 @@ export class Program<IDL extends Idl = Idl> {
* }, * },
* }); * });
* ``` * ```
* @deprecated
*/ */
readonly transaction: TransactionNamespace<IDL>; readonly transaction: TransactionNamespace<IDL>;
@ -197,6 +200,7 @@ export class Program<IDL extends Idl = Idl> {
* }, * },
* }); * });
* ``` * ```
* @deprecated
*/ */
readonly simulate: SimulateNamespace<IDL>; readonly simulate: SimulateNamespace<IDL>;

View File

@ -10,7 +10,6 @@ import RpcFactory, { RpcNamespace } from "./rpc.js";
import AccountFactory, { AccountNamespace } from "./account.js"; import AccountFactory, { AccountNamespace } from "./account.js";
import SimulateFactory, { SimulateNamespace } from "./simulate.js"; import SimulateFactory, { SimulateNamespace } from "./simulate.js";
import { parseIdlErrors } from "../common.js"; import { parseIdlErrors } from "../common.js";
import { AllInstructions } from "./types.js";
import { MethodsBuilderFactory, MethodsNamespace } from "./methods"; import { MethodsBuilderFactory, MethodsNamespace } from "./methods";
// Re-exports. // Re-exports.
@ -55,8 +54,8 @@ export default class NamespaceFactory {
const state = StateFactory.build(idl, coder, programId, provider); const state = StateFactory.build(idl, coder, programId, provider);
idl.instructions.forEach(<I extends AllInstructions<IDL>>(idlIx: I) => { idl.instructions.forEach((idlIx) => {
const ixItem = InstructionFactory.build<IDL, I>( const ixItem = InstructionFactory.build<IDL, typeof idlIx>(
idlIx, idlIx,
(ixName, ix) => coder.instruction.encode(ixName, ix), (ixName, ix) => coder.instruction.encode(ixName, ix),
programId programId
@ -72,7 +71,7 @@ export default class NamespaceFactory {
programId, programId,
idl idl
); );
const methodItem = MethodsBuilderFactory.build( const methodItem = MethodsBuilderFactory.build<IDL, typeof idlIx>(
provider, provider,
programId, programId,
idlIx, idlIx,

View File

@ -17,6 +17,7 @@ import { SimulateFn } from "./simulate.js";
import Provider from "../../provider.js"; import Provider from "../../provider.js";
import { AccountNamespace } from "./account.js"; import { AccountNamespace } from "./account.js";
import { AccountsResolver } from "../accounts-resolver.js"; import { AccountsResolver } from "../accounts-resolver.js";
import { Accounts } from "../context.js";
export type MethodsNamespace< export type MethodsNamespace<
IDL extends Idl = Idl, IDL extends Idl = Idl,
@ -33,9 +34,9 @@ export class MethodsBuilderFactory {
rpcFn: RpcFn<IDL>, rpcFn: RpcFn<IDL>,
simulateFn: SimulateFn<IDL>, simulateFn: SimulateFn<IDL>,
accountNamespace: AccountNamespace<IDL> accountNamespace: AccountNamespace<IDL>
): MethodsFn<IDL, I, any> { ): MethodsFn<IDL, I, MethodsBuilder<IDL, I>> {
const request: MethodsFn<IDL, I, any> = (...args) => { return (...args) =>
return new MethodsBuilder( new MethodsBuilder(
args, args,
ixFn, ixFn,
txFn, txFn,
@ -46,13 +47,11 @@ export class MethodsBuilderFactory {
idlIx, idlIx,
accountNamespace accountNamespace
); );
};
return request;
} }
} }
export class MethodsBuilder<IDL extends Idl, I extends AllInstructions<IDL>> { export class MethodsBuilder<IDL extends Idl, I extends AllInstructions<IDL>> {
readonly _accounts: { [name: string]: PublicKey } = {}; private readonly _accounts: { [name: string]: PublicKey } = {};
private _remainingAccounts: Array<AccountMeta> = []; private _remainingAccounts: Array<AccountMeta> = [];
private _signers: Array<Signer> = []; private _signers: Array<Signer> = [];
private _preInstructions: Array<TransactionInstruction> = []; private _preInstructions: Array<TransactionInstruction> = [];
@ -80,8 +79,9 @@ export class MethodsBuilder<IDL extends Idl, I extends AllInstructions<IDL>> {
); );
} }
// TODO: don't use any. public accounts(
public accounts(accounts: any): MethodsBuilder<IDL, I> { accounts: Partial<Accounts<I["accounts"][number]>>
): MethodsBuilder<IDL, I> {
Object.assign(this._accounts, accounts); Object.assign(this._accounts, accounts);
return this; return this;
} }
@ -112,7 +112,7 @@ export class MethodsBuilder<IDL extends Idl, I extends AllInstructions<IDL>> {
return this; return this;
} }
public async rpc(options: ConfirmOptions): Promise<TransactionSignature> { public async rpc(options?: ConfirmOptions): Promise<TransactionSignature> {
await this._accountsResolver.resolve(); await this._accountsResolver.resolve();
// @ts-ignore // @ts-ignore
return this._rpcFn(...this._args, { return this._rpcFn(...this._args, {
@ -126,7 +126,7 @@ export class MethodsBuilder<IDL extends Idl, I extends AllInstructions<IDL>> {
} }
public async simulate( public async simulate(
options: ConfirmOptions options?: ConfirmOptions
): Promise<SimulateResponse<any, any>> { ): Promise<SimulateResponse<any, any>> {
await this._accountsResolver.resolve(); await this._accountsResolver.resolve();
// @ts-ignore // @ts-ignore

View File

@ -10,6 +10,7 @@ import {
IdlTypeDefTyStruct, IdlTypeDefTyStruct,
} from "../../idl"; } from "../../idl";
import { Accounts, Context } from "../context"; import { Accounts, Context } from "../context";
import { MethodsBuilder } from "./methods";
/** /**
* All instructions for an IDL. * All instructions for an IDL.
@ -66,7 +67,11 @@ export type MakeInstructionsNamespace<
}; };
export type MakeMethodsNamespace<IDL extends Idl, I extends IdlInstruction> = { export type MakeMethodsNamespace<IDL extends Idl, I extends IdlInstruction> = {
[M in keyof InstructionMap<I>]: MethodsFn<IDL, InstructionMap<I>[M], any>; [M in keyof InstructionMap<I>]: MethodsFn<
IDL,
InstructionMap<I>[M],
MethodsBuilder<IDL, InstructionMap<I>[M]>
>;
}; };
export type InstructionContextFn< export type InstructionContextFn<