The Solana program and TypeScript SDK that handles on-chain marketplace transactions (e.g. bidding, buying editions) for Formfunction.
- Mainnet address:
formn3hJtt8gvVKxpCfzCJGuoz6CNUFcULFZW18iTpC
- Devnet address:
devmBQyHHBPiLcuCqbWWRYxCG33ntAfPD5nXZeLd4eX
Use the same version of Anchor CLI as .github/workflows/release-package.yml
I.e. run avm use 0.24.2
- Install Rust, Solana, Anchor: https://book.anchor-lang.com/chapter_2/installation.html
- Install Solana CLI
- Run
yarn
- Run
yarn test
- Run
yarn test-cargo
If everything is setup correctly, all tests should pass and you should have a localnet setup ready to go!
High-level overview:
- The core instruction set of the Auction House program lives in
src/lib.rs
- The JavaScript SDK lives in
src/solana/auction-house/AuctionHouseSdk.ts
- The SDK interfaces with the Auction House program via clients generated from IDL produced by Anchor (see
src/types/AuctionHouseProgram.ts
and the instruction wrappers insrc/solana/auction-house/instructions
to see this in action)
- The SDK interfaces with the Auction House program via clients generated from IDL produced by Anchor (see
An example E2E change might look like:
- Instruction is added/updated in
src/lib.rs
- Run
yarn build-program
to generate types + JS clients - Add/update corresponding instruction in JS SDK
- Write tests in
src/tests/formfn-auction-house.ts
- Run
yarn test
to verify changes
As we are deploying updates to a program being used in production, we must be careful to ensure that our upgrades are backwards compatible (i.e., doesn't break existing production experience).
See this blog post for more info on program backwards compatibility.
- Calling into external programs in localnet: if you are calling into external programs and you want to test this on localnet, you'll need to download the binary and specify it in
Anchor.toml
:solana program dump <program id> artifacts/deploy/<name>.so --url mainnet-beta
- In
Anchor.toml
: add a new[[test.genesis]]
entry:
[[test.genesis]]
address = "<program id>"
program = "artifacts/deploy/<name>.so"
-
Cross-program invocation with unauthorized signer or writable account when calling
invoke_signed
: this can be either because:- The signature is invalid (i.e., the current program cannot sign for the specified PDA)
- There are accounts that were passed in that should be marked as writable but they are not
- Sometimes the easiest way is to just check the source code of the instruction being invoked and see if the accounts are being marked as read-only or not (if not, it needs to be writable)
-
Check the tests: sometimes the tests will no longer testing behavior that is considered valid based on your changes so it's good to verify that the test isn't fault
Note that the tests run in parallel by default, and that an address lookup table is setup and deployed prior to the test run. This ALT is shared across all of the tests.
# Run tests using Anchor (spins up local validator and deploys program)
$ yarn test
# Run with tests with SPL_TOKEN enabled
$ yarn test-spl
# Run tests using Anchor without silencing console.error output
$ yarn test-debug
# Run Rust unit tests with Cargo
$ yarn test-cargo
# Run Rust unit tests with Cargo with extra logging
$ yarn test-cargo-debug
Run yarn test
or yarn test-debug
and pass in a file pattern for the test you want to run:
$ yarn test buyEditionAllowlist.test.ts
If you for some reason need the tests to run serially, rather than in parallel, you can run:
$ RUN_IN_BAND=true yarn test
If you want to log transaction sizes in the tests, you can run:
$ LOG_TX_SIZE=true yarn test
Run yarn build-program
.
- Create new binary by pushing a new tag
- Download new binary to computer (can't use GitHub URL because our repo is private)
- Make sure deployer account (run
goki show
to find pubkey) has enough SOL (needs ~4 SOL) - Run
goki upgrade-local -c mainnet -l releases/formfn_auction_house-VERSION.so -p formn3hJtt8gvVKxpCfzCJGuoz6CNUFcULFZW18iTpC -u usb://ledger
. Make sure the Ledger is connected - Sign transactions with ledger
- Update the NPM package if necessary, and bump it wherever it's used
solana program dump formn3hJtt8gvVKxpCfzCJGuoz6CNUFcULFZW18iTpC deployed.so
goki pull releases/formfn_auction_house-VERSION.so
head -c NUM_BYTES deployed.so > deployed-trimmed.so
goki pull deployed-trimmed.so
Compare SHA256
hashes of the goki pull
commands to verify the deployed release is indeed the version you expect it to be.
From the root dir on an untouched checkout of main
, run
./scripts/deploy-dev.sh
From the root dir on an untouched checkout of main
, run
./scripts/deploy-test.sh
You may need to follow this to get the deployment to work: https://stackoverflow.com/questions/70437644/error-custom-invalid-blockhash-when-solana-program-deploy/70664369#70664369
$ npm login --scope=@formfunction-hq --registry=https://npm.pkg.github..com
Username: formfunction-hq
Password: YOUR_PAT
Email: (this IS public) YOUR_EMAIL
Logged in as formfunction-hq to scope @formfunction-hq on https://npm.pkg.github.com/.
OR, create a .npmrc
with the following:
@formfunction-hq:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_PAT
yarn npm version prerelease --preid=alpha
. Doing this bumps the version, and creates a new tag + commitgit push origin NEW_TAG
. Doing this will push the new tag, which will causerelease-package.yml
to run and publish a new package (with the same version as the tag)- Note that when upgrading the client SDK in the monorepo, you need to upgrade the
frontend
shared
andserver
packages.