From c4d57567d201470159016046ae56f53abecb5d4b Mon Sep 17 00:00:00 2001 From: Noah Gundotra Date: Mon, 6 Jun 2022 10:08:18 -0700 Subject: [PATCH 1/8] add solita bubblegum --- contracts/sdk/bubblegum/idl/bubblegum.json | 1006 +++++++++++++++++ contracts/sdk/bubblegum/package.json | 11 + contracts/sdk/bubblegum/solita.js | 74 ++ .../bubblegum/src/generated/accounts/Nonce.ts | 154 +++ .../src/generated/accounts/Voucher.ts | 156 +++ .../bubblegum/src/generated/accounts/index.ts | 2 + .../sdk/bubblegum/src/generated/index.ts | 20 + .../src/generated/instructions/burn.ts | 124 ++ .../generated/instructions/cancelRedeem.ts | 115 ++ .../src/generated/instructions/compress.ts | 163 +++ .../src/generated/instructions/createTree.ts | 110 ++ .../src/generated/instructions/decompress.ts | 173 +++ .../src/generated/instructions/delegate.ts | 140 +++ .../src/generated/instructions/index.ts | 10 + .../generated/instructions/initializeNonce.ts | 82 ++ .../src/generated/instructions/mint.ts | 141 +++ .../src/generated/instructions/redeem.ts | 139 +++ .../src/generated/instructions/transfer.ts | 134 +++ .../src/generated/types/Collection.ts | 26 + .../bubblegum/src/generated/types/Creator.ts | 28 + .../src/generated/types/InstructionName.ts | 29 + .../src/generated/types/LeafSchema.ts | 35 + .../src/generated/types/MetadataArgs.ts | 52 + .../generated/types/TokenProgramVersion.ts | 24 + .../src/generated/types/TokenStandard.ts | 26 + .../src/generated/types/UseMethod.ts | 25 + .../sdk/bubblegum/src/generated/types/Uses.ts | 27 + .../bubblegum/src/generated/types/Version.ts | 24 + .../bubblegum/src/generated/types/index.ts | 10 + 29 files changed, 3060 insertions(+) create mode 100644 contracts/sdk/bubblegum/idl/bubblegum.json create mode 100644 contracts/sdk/bubblegum/package.json create mode 100644 contracts/sdk/bubblegum/solita.js create mode 100644 contracts/sdk/bubblegum/src/generated/accounts/Nonce.ts create mode 100644 contracts/sdk/bubblegum/src/generated/accounts/Voucher.ts create mode 100644 contracts/sdk/bubblegum/src/generated/accounts/index.ts create mode 100644 contracts/sdk/bubblegum/src/generated/index.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/burn.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/cancelRedeem.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/compress.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/createTree.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/decompress.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/delegate.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/index.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/initializeNonce.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/mint.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/redeem.ts create mode 100644 contracts/sdk/bubblegum/src/generated/instructions/transfer.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/Collection.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/Creator.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/InstructionName.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/LeafSchema.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/MetadataArgs.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/TokenProgramVersion.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/TokenStandard.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/UseMethod.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/Uses.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/Version.ts create mode 100644 contracts/sdk/bubblegum/src/generated/types/index.ts diff --git a/contracts/sdk/bubblegum/idl/bubblegum.json b/contracts/sdk/bubblegum/idl/bubblegum.json new file mode 100644 index 00000000000..383fe94a033 --- /dev/null +++ b/contracts/sdk/bubblegum/idl/bubblegum.json @@ -0,0 +1,1006 @@ +{ + "version": "0.1.0", + "name": "bubblegum", + "instructions": [ + { + "name": "initializeNonce", + "accounts": [ + { + "name": "nonce", + "isMut": true, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "createTree", + "accounts": [ + { + "name": "treeCreator", + "isMut": false, + "isSigner": true + }, + { + "name": "authority", + "isMut": false, + "isSigner": false + }, + { + "name": "gummyrollProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxDepth", + "type": "u32" + }, + { + "name": "maxBufferSize", + "type": "u32" + } + ] + }, + { + "name": "mint", + "accounts": [ + { + "name": "mintAuthority", + "isMut": false, + "isSigner": true + }, + { + "name": "authority", + "isMut": false, + "isSigner": false + }, + { + "name": "nonce", + "isMut": true, + "isSigner": false + }, + { + "name": "gummyrollProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "owner", + "isMut": false, + "isSigner": true + }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "version", + "type": { + "defined": "Version" + } + }, + { + "name": "message", + "type": { + "defined": "MetadataArgs" + } + } + ] + }, + { + "name": "transfer", + "accounts": [ + { + "name": "authority", + "isMut": false, + "isSigner": false + }, + { + "name": "owner", + "isMut": false, + "isSigner": false + }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "newOwner", + "isMut": false, + "isSigner": false + }, + { + "name": "gummyrollProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "version", + "type": { + "defined": "Version" + } + }, + { + "name": "root", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "dataHash", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "creatorHash", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "nonce", + "type": "u128" + }, + { + "name": "index", + "type": "u32" + } + ] + }, + { + "name": "delegate", + "accounts": [ + { + "name": "authority", + "isMut": false, + "isSigner": false + }, + { + "name": "owner", + "isMut": false, + "isSigner": true + }, + { + "name": "previousDelegate", + "isMut": false, + "isSigner": false + }, + { + "name": "newDelegate", + "isMut": false, + "isSigner": false + }, + { + "name": "gummyrollProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "version", + "type": { + "defined": "Version" + } + }, + { + "name": "root", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "dataHash", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "creatorHash", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "nonce", + "type": "u128" + }, + { + "name": "index", + "type": "u32" + } + ] + }, + { + "name": "burn", + "accounts": [ + { + "name": "authority", + "isMut": false, + "isSigner": false + }, + { + "name": "gummyrollProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "owner", + "isMut": false, + "isSigner": false + }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "version", + "type": { + "defined": "Version" + } + }, + { + "name": "root", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "dataHash", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "creatorHash", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "nonce", + "type": "u128" + }, + { + "name": "index", + "type": "u32" + } + ] + }, + { + "name": "redeem", + "accounts": [ + { + "name": "authority", + "isMut": false, + "isSigner": false + }, + { + "name": "gummyrollProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "owner", + "isMut": true, + "isSigner": true + }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + }, + { + "name": "voucher", + "isMut": true, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "version", + "type": { + "defined": "Version" + } + }, + { + "name": "root", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "dataHash", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "creatorHash", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "nonce", + "type": "u128" + }, + { + "name": "index", + "type": "u32" + } + ] + }, + { + "name": "cancelRedeem", + "accounts": [ + { + "name": "authority", + "isMut": false, + "isSigner": false + }, + { + "name": "gummyrollProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + }, + { + "name": "voucher", + "isMut": true, + "isSigner": false + }, + { + "name": "owner", + "isMut": true, + "isSigner": true + } + ], + "args": [ + { + "name": "root", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "decompress", + "accounts": [ + { + "name": "voucher", + "isMut": true, + "isSigner": false + }, + { + "name": "owner", + "isMut": true, + "isSigner": true + }, + { + "name": "tokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "mint", + "isMut": true, + "isSigner": false + }, + { + "name": "mintAuthority", + "isMut": false, + "isSigner": false + }, + { + "name": "metadata", + "isMut": true, + "isSigner": false + }, + { + "name": "masterEdition", + "isMut": true, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "sysvarRent", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenMetadataProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "associatedTokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "metadata", + "type": { + "defined": "MetadataArgs" + } + } + ] + }, + { + "name": "compress", + "accounts": [ + { + "name": "authority", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": false, + "isSigner": false + }, + { + "name": "owner", + "isMut": false, + "isSigner": true + }, + { + "name": "delegate", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "mint", + "isMut": true, + "isSigner": false + }, + { + "name": "metadata", + "isMut": true, + "isSigner": false + }, + { + "name": "masterEdition", + "isMut": true, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenMetadataProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "gummyrollProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [] + } + ], + "accounts": [ + { + "name": "Nonce", + "type": { + "kind": "struct", + "fields": [ + { + "name": "count", + "type": "u128" + } + ] + } + }, + { + "name": "Voucher", + "type": { + "kind": "struct", + "fields": [ + { + "name": "leafSchema", + "type": { + "defined": "LeafSchema" + } + }, + { + "name": "index", + "type": "u32" + }, + { + "name": "merkleSlab", + "type": "publicKey" + } + ] + } + } + ], + "types": [ + { + "name": "LeafSchema", + "type": { + "kind": "struct", + "fields": [ + { + "name": "version", + "type": { + "defined": "Version" + } + }, + { + "name": "owner", + "type": "publicKey" + }, + { + "name": "delegate", + "type": "publicKey" + }, + { + "name": "nonce", + "type": "u128" + }, + { + "name": "dataHash", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "creatorHash", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + } + }, + { + "name": "Creator", + "type": { + "kind": "struct", + "fields": [ + { + "name": "address", + "type": "publicKey" + }, + { + "name": "verified", + "type": "bool" + }, + { + "name": "share", + "type": "u8" + } + ] + } + }, + { + "name": "Uses", + "type": { + "kind": "struct", + "fields": [ + { + "name": "useMethod", + "type": { + "defined": "UseMethod" + } + }, + { + "name": "remaining", + "type": "u64" + }, + { + "name": "total", + "type": "u64" + } + ] + } + }, + { + "name": "Collection", + "type": { + "kind": "struct", + "fields": [ + { + "name": "verified", + "type": "bool" + }, + { + "name": "key", + "type": "publicKey" + } + ] + } + }, + { + "name": "MetadataArgs", + "type": { + "kind": "struct", + "fields": [ + { + "name": "name", + "docs": [ + "The name of the asset" + ], + "type": "string" + }, + { + "name": "symbol", + "docs": [ + "The symbol for the asset" + ], + "type": "string" + }, + { + "name": "uri", + "docs": [ + "URI pointing to JSON representing the asset" + ], + "type": "string" + }, + { + "name": "sellerFeeBasisPoints", + "docs": [ + "Royalty basis points that goes to creators in secondary sales (0-10000)" + ], + "type": "u16" + }, + { + "name": "primarySaleHappened", + "type": "bool" + }, + { + "name": "isMutable", + "type": "bool" + }, + { + "name": "editionNonce", + "docs": [ + "nonce for easy calculation of editions, if present" + ], + "type": { + "option": "u8" + } + }, + { + "name": "tokenStandard", + "docs": [ + "Since we cannot easily change Metadata, we add the new DataV2 fields here at the end." + ], + "type": { + "option": { + "defined": "TokenStandard" + } + } + }, + { + "name": "collection", + "docs": [ + "Collection" + ], + "type": { + "option": { + "defined": "Collection" + } + } + }, + { + "name": "uses", + "docs": [ + "Uses" + ], + "type": { + "option": { + "defined": "Uses" + } + } + }, + { + "name": "tokenProgramVersion", + "type": { + "defined": "TokenProgramVersion" + } + }, + { + "name": "creators", + "type": { + "vec": { + "defined": "Creator" + } + } + } + ] + } + }, + { + "name": "Version", + "type": { + "kind": "enum", + "variants": [ + { + "name": "V0" + } + ] + } + }, + { + "name": "TokenProgramVersion", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Original" + }, + { + "name": "Token2022" + } + ] + } + }, + { + "name": "TokenStandard", + "type": { + "kind": "enum", + "variants": [ + { + "name": "NonFungible" + }, + { + "name": "FungibleAsset" + }, + { + "name": "Fungible" + }, + { + "name": "NonFungibleEdition" + } + ] + } + }, + { + "name": "UseMethod", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Burn" + }, + { + "name": "Multiple" + }, + { + "name": "Single" + } + ] + } + }, + { + "name": "InstructionName", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Unknown" + }, + { + "name": "Mint" + }, + { + "name": "Redeem" + }, + { + "name": "CancelRedeem" + }, + { + "name": "Transfer" + }, + { + "name": "Delegate" + }, + { + "name": "Decompress" + } + ] + } + } + ], + "events": [ + { + "name": "LeafSchemaEvent", + "fields": [ + { + "name": "version", + "type": { + "defined": "Version" + }, + "index": false + }, + { + "name": "owner", + "type": "publicKey", + "index": false + }, + { + "name": "delegate", + "type": "publicKey", + "index": false + }, + { + "name": "nonce", + "type": "u128", + "index": false + }, + { + "name": "dataHash", + "type": { + "array": [ + "u8", + 32 + ] + }, + "index": false + }, + { + "name": "creatorHash", + "type": { + "array": [ + "u8", + 32 + ] + }, + "index": false + }, + { + "name": "leafHash", + "type": { + "array": [ + "u8", + 32 + ] + }, + "index": false + } + ] + } + ], + "metadata": { + "address": "BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o" + } +} \ No newline at end of file diff --git a/contracts/sdk/bubblegum/package.json b/contracts/sdk/bubblegum/package.json new file mode 100644 index 00000000000..1332340721b --- /dev/null +++ b/contracts/sdk/bubblegum/package.json @@ -0,0 +1,11 @@ +{ + "name": "bubblegum", + "version": "1.0.0", + "description": "SDK for MPL Bubblegum contract", + "main": "index.js", + "license": "MIT", + "dependencies": { + "@metaplex-foundation/rustbin": "^0.3.1", + "@metaplex-foundation/solita": "^0.8.2" + } +} diff --git a/contracts/sdk/bubblegum/solita.js b/contracts/sdk/bubblegum/solita.js new file mode 100644 index 00000000000..65b394f9b17 --- /dev/null +++ b/contracts/sdk/bubblegum/solita.js @@ -0,0 +1,74 @@ +const path = require('path'); +const { + rustbinMatch, + confirmAutoMessageConsole, +} = require('@metaplex-foundation/rustbin') +const { spawn } = require('child_process'); +const { Solita } = require('@metaplex-foundation/solita'); +const { writeFile } = require('fs/promises'); +const { fstat, existsSync } = require('fs'); + +const PROGRAM_NAME = 'bubblegum'; +const PROGRAM_ID = 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o'; + +const programDir = path.join(__dirname, '..', '..', 'programs', 'bubblegum'); +const cargoToml = path.join(programDir, 'Cargo.toml') +const generatedIdlDir = path.join(__dirname, 'idl'); +const generatedSDKDir = path.join(__dirname, 'src', 'generated'); +const rootDir = path.join(__dirname, '.crates') +const rustbinConfig = { + rootDir, + binaryName: 'anchor', + binaryCrateName: 'anchor-cli', + libName: 'anchor-lang', + dryRun: false, + cargoToml, +} + +async function main() { + const anchorExecutable = ("~/Documents/core/candyland/deps/anchor/target/debug/anchor").replace("~", process.env.HOME); + if (!existsSync(anchorExecutable)) { + console.log(`Could not find: ${anchorExecutable}`); + throw new Error("Please `cd candyland/deps/anchor/anchor-cli` && cargo build`") + } + const anchor = spawn(anchorExecutable, ['build', '--idl', generatedIdlDir], { cwd: programDir }) + .on('error', (err) => { + console.error(err); + // @ts-ignore this err does have a code + if (err.code === 'ENOENT') { + console.error( + 'Ensure that `anchor` is installed and in your path, see:\n https://project-serum.github.io/anchor/getting-started/installation.html#install-anchor\n', + ); + } + process.exit(1); + }) + .on('exit', () => { + console.log('IDL written to: %s', path.join(generatedIdlDir, `${PROGRAM_NAME}.json`)); + generateTypeScriptSDK(); + }); + + anchor.stdout.on('data', (buf) => console.log(buf.toString('utf8'))); + anchor.stderr.on('data', (buf) => console.error(buf.toString('utf8'))); +} + +async function generateTypeScriptSDK() { + console.error('Generating TypeScript SDK to %s', generatedSDKDir); + const generatedIdlPath = path.join(generatedIdlDir, `${PROGRAM_NAME}.json`); + + const idl = require(generatedIdlPath); + if (idl.metadata?.address == null) { + idl.metadata = { ...idl.metadata, address: PROGRAM_ID }; + await writeFile(generatedIdlPath, JSON.stringify(idl, null, 2)); + } + const gen = new Solita(idl, { formatCode: true }); + await gen.renderAndWriteTo(generatedSDKDir); + + console.error('Success!'); + + process.exit(0); +} + +main().catch((err) => { + console.error(err) + process.exit(1) +}) diff --git a/contracts/sdk/bubblegum/src/generated/accounts/Nonce.ts b/contracts/sdk/bubblegum/src/generated/accounts/Nonce.ts new file mode 100644 index 00000000000..0b4fbc5031a --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/accounts/Nonce.ts @@ -0,0 +1,154 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * Arguments used to create {@link Nonce} + * @category Accounts + * @category generated + */ +export type NonceArgs = { + count: beet.bignum +} + +const nonceDiscriminator = [143, 197, 147, 95, 106, 165, 50, 43] +/** + * Holds the data for the {@link Nonce} Account and provides de/serialization + * functionality for that data + * + * @category Accounts + * @category generated + */ +export class Nonce implements NonceArgs { + private constructor(readonly count: beet.bignum) {} + + /** + * Creates a {@link Nonce} instance from the provided args. + */ + static fromArgs(args: NonceArgs) { + return new Nonce(args.count) + } + + /** + * Deserializes the {@link Nonce} from the data of the provided {@link web3.AccountInfo}. + * @returns a tuple of the account data and the offset up to which the buffer was read to obtain it. + */ + static fromAccountInfo( + accountInfo: web3.AccountInfo, + offset = 0 + ): [Nonce, number] { + return Nonce.deserialize(accountInfo.data, offset) + } + + /** + * Retrieves the account info from the provided address and deserializes + * the {@link Nonce} from its data. + * + * @throws Error if no account info is found at the address or if deserialization fails + */ + static async fromAccountAddress( + connection: web3.Connection, + address: web3.PublicKey + ): Promise { + const accountInfo = await connection.getAccountInfo(address) + if (accountInfo == null) { + throw new Error(`Unable to find Nonce account at ${address}`) + } + return Nonce.fromAccountInfo(accountInfo, 0)[0] + } + + /** + * Deserializes the {@link Nonce} from the provided data Buffer. + * @returns a tuple of the account data and the offset up to which the buffer was read to obtain it. + */ + static deserialize(buf: Buffer, offset = 0): [Nonce, number] { + return nonceBeet.deserialize(buf, offset) + } + + /** + * Serializes the {@link Nonce} into a Buffer. + * @returns a tuple of the created Buffer and the offset up to which the buffer was written to store it. + */ + serialize(): [Buffer, number] { + return nonceBeet.serialize({ + accountDiscriminator: nonceDiscriminator, + ...this, + }) + } + + /** + * Returns the byteSize of a {@link Buffer} holding the serialized data of + * {@link Nonce} + */ + static get byteSize() { + return nonceBeet.byteSize + } + + /** + * Fetches the minimum balance needed to exempt an account holding + * {@link Nonce} data from rent + * + * @param connection used to retrieve the rent exemption information + */ + static async getMinimumBalanceForRentExemption( + connection: web3.Connection, + commitment?: web3.Commitment + ): Promise { + return connection.getMinimumBalanceForRentExemption( + Nonce.byteSize, + commitment + ) + } + + /** + * Determines if the provided {@link Buffer} has the correct byte size to + * hold {@link Nonce} data. + */ + static hasCorrectByteSize(buf: Buffer, offset = 0) { + return buf.byteLength - offset === Nonce.byteSize + } + + /** + * Returns a readable version of {@link Nonce} properties + * and can be used to convert to JSON and/or logging + */ + pretty() { + return { + count: (() => { + const x = <{ toNumber: () => number }>this.count + if (typeof x.toNumber === 'function') { + try { + return x.toNumber() + } catch (_) { + return x + } + } + return x + })(), + } + } +} + +/** + * @category Accounts + * @category generated + */ +export const nonceBeet = new beet.BeetStruct< + Nonce, + NonceArgs & { + accountDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['accountDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['count', beet.u128], + ], + Nonce.fromArgs, + 'Nonce' +) diff --git a/contracts/sdk/bubblegum/src/generated/accounts/Voucher.ts b/contracts/sdk/bubblegum/src/generated/accounts/Voucher.ts new file mode 100644 index 00000000000..335a1c3fc72 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/accounts/Voucher.ts @@ -0,0 +1,156 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as web3 from '@solana/web3.js' +import * as beet from '@metaplex-foundation/beet' +import * as beetSolana from '@metaplex-foundation/beet-solana' +import { LeafSchema, leafSchemaBeet } from '../types/LeafSchema' + +/** + * Arguments used to create {@link Voucher} + * @category Accounts + * @category generated + */ +export type VoucherArgs = { + leafSchema: LeafSchema + index: number + merkleSlab: web3.PublicKey +} + +const voucherDiscriminator = [191, 204, 149, 234, 213, 165, 13, 65] +/** + * Holds the data for the {@link Voucher} Account and provides de/serialization + * functionality for that data + * + * @category Accounts + * @category generated + */ +export class Voucher implements VoucherArgs { + private constructor( + readonly leafSchema: LeafSchema, + readonly index: number, + readonly merkleSlab: web3.PublicKey + ) {} + + /** + * Creates a {@link Voucher} instance from the provided args. + */ + static fromArgs(args: VoucherArgs) { + return new Voucher(args.leafSchema, args.index, args.merkleSlab) + } + + /** + * Deserializes the {@link Voucher} from the data of the provided {@link web3.AccountInfo}. + * @returns a tuple of the account data and the offset up to which the buffer was read to obtain it. + */ + static fromAccountInfo( + accountInfo: web3.AccountInfo, + offset = 0 + ): [Voucher, number] { + return Voucher.deserialize(accountInfo.data, offset) + } + + /** + * Retrieves the account info from the provided address and deserializes + * the {@link Voucher} from its data. + * + * @throws Error if no account info is found at the address or if deserialization fails + */ + static async fromAccountAddress( + connection: web3.Connection, + address: web3.PublicKey + ): Promise { + const accountInfo = await connection.getAccountInfo(address) + if (accountInfo == null) { + throw new Error(`Unable to find Voucher account at ${address}`) + } + return Voucher.fromAccountInfo(accountInfo, 0)[0] + } + + /** + * Deserializes the {@link Voucher} from the provided data Buffer. + * @returns a tuple of the account data and the offset up to which the buffer was read to obtain it. + */ + static deserialize(buf: Buffer, offset = 0): [Voucher, number] { + return voucherBeet.deserialize(buf, offset) + } + + /** + * Serializes the {@link Voucher} into a Buffer. + * @returns a tuple of the created Buffer and the offset up to which the buffer was written to store it. + */ + serialize(): [Buffer, number] { + return voucherBeet.serialize({ + accountDiscriminator: voucherDiscriminator, + ...this, + }) + } + + /** + * Returns the byteSize of a {@link Buffer} holding the serialized data of + * {@link Voucher} + */ + static get byteSize() { + return voucherBeet.byteSize + } + + /** + * Fetches the minimum balance needed to exempt an account holding + * {@link Voucher} data from rent + * + * @param connection used to retrieve the rent exemption information + */ + static async getMinimumBalanceForRentExemption( + connection: web3.Connection, + commitment?: web3.Commitment + ): Promise { + return connection.getMinimumBalanceForRentExemption( + Voucher.byteSize, + commitment + ) + } + + /** + * Determines if the provided {@link Buffer} has the correct byte size to + * hold {@link Voucher} data. + */ + static hasCorrectByteSize(buf: Buffer, offset = 0) { + return buf.byteLength - offset === Voucher.byteSize + } + + /** + * Returns a readable version of {@link Voucher} properties + * and can be used to convert to JSON and/or logging + */ + pretty() { + return { + leafSchema: this.leafSchema, + index: this.index, + merkleSlab: this.merkleSlab.toBase58(), + } + } +} + +/** + * @category Accounts + * @category generated + */ +export const voucherBeet = new beet.BeetStruct< + Voucher, + VoucherArgs & { + accountDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['accountDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['leafSchema', leafSchemaBeet], + ['index', beet.u32], + ['merkleSlab', beetSolana.publicKey], + ], + Voucher.fromArgs, + 'Voucher' +) diff --git a/contracts/sdk/bubblegum/src/generated/accounts/index.ts b/contracts/sdk/bubblegum/src/generated/accounts/index.ts new file mode 100644 index 00000000000..7dfec8ad134 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/accounts/index.ts @@ -0,0 +1,2 @@ +export * from './Nonce' +export * from './Voucher' diff --git a/contracts/sdk/bubblegum/src/generated/index.ts b/contracts/sdk/bubblegum/src/generated/index.ts new file mode 100644 index 00000000000..31289687610 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/index.ts @@ -0,0 +1,20 @@ +import { PublicKey } from '@solana/web3.js' +export * from './accounts' +export * from './instructions' +export * from './types' + +/** + * Program address + * + * @category constants + * @category generated + */ +export const PROGRAM_ADDRESS = 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + +/** + * Program public key + * + * @category constants + * @category generated + */ +export const PROGRAM_ID = new PublicKey(PROGRAM_ADDRESS) diff --git a/contracts/sdk/bubblegum/src/generated/instructions/burn.ts b/contracts/sdk/bubblegum/src/generated/instructions/burn.ts new file mode 100644 index 00000000000..2fd95e083bb --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/burn.ts @@ -0,0 +1,124 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' +import { Version, versionBeet } from '../types/Version' + +/** + * @category Instructions + * @category Burn + * @category generated + */ +export type BurnInstructionArgs = { + version: Version + root: number[] /* size: 32 */ + dataHash: number[] /* size: 32 */ + creatorHash: number[] /* size: 32 */ + nonce: beet.bignum + index: number +} +/** + * @category Instructions + * @category Burn + * @category generated + */ +export const burnStruct = new beet.BeetArgsStruct< + BurnInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['version', versionBeet], + ['root', beet.uniformFixedSizeArray(beet.u8, 32)], + ['dataHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ['creatorHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ['nonce', beet.u128], + ['index', beet.u32], + ], + 'BurnInstructionArgs' +) +/** + * Accounts required by the _burn_ instruction + * + * @property [] authority + * @property [] gummyrollProgram + * @property [] owner + * @property [] delegate + * @property [_writable_] merkleSlab + * @category Instructions + * @category Burn + * @category generated + */ +export type BurnInstructionAccounts = { + authority: web3.PublicKey + gummyrollProgram: web3.PublicKey + owner: web3.PublicKey + delegate: web3.PublicKey + merkleSlab: web3.PublicKey +} + +export const burnInstructionDiscriminator = [116, 110, 29, 56, 107, 219, 42, 93] + +/** + * Creates a _Burn_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category Burn + * @category generated + */ +export function createBurnInstruction( + accounts: BurnInstructionAccounts, + args: BurnInstructionArgs +) { + const { authority, gummyrollProgram, owner, delegate, merkleSlab } = accounts + + const [data] = burnStruct.serialize({ + instructionDiscriminator: burnInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: authority, + isWritable: false, + isSigner: false, + }, + { + pubkey: gummyrollProgram, + isWritable: false, + isSigner: false, + }, + { + pubkey: owner, + isWritable: false, + isSigner: false, + }, + { + pubkey: delegate, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/instructions/cancelRedeem.ts b/contracts/sdk/bubblegum/src/generated/instructions/cancelRedeem.ts new file mode 100644 index 00000000000..57aeea7e2f5 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/cancelRedeem.ts @@ -0,0 +1,115 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * @category Instructions + * @category CancelRedeem + * @category generated + */ +export type CancelRedeemInstructionArgs = { + root: number[] /* size: 32 */ +} +/** + * @category Instructions + * @category CancelRedeem + * @category generated + */ +export const cancelRedeemStruct = new beet.BeetArgsStruct< + CancelRedeemInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['root', beet.uniformFixedSizeArray(beet.u8, 32)], + ], + 'CancelRedeemInstructionArgs' +) +/** + * Accounts required by the _cancelRedeem_ instruction + * + * @property [] authority + * @property [] gummyrollProgram + * @property [_writable_] merkleSlab + * @property [_writable_] voucher + * @property [_writable_, **signer**] owner + * @category Instructions + * @category CancelRedeem + * @category generated + */ +export type CancelRedeemInstructionAccounts = { + authority: web3.PublicKey + gummyrollProgram: web3.PublicKey + merkleSlab: web3.PublicKey + voucher: web3.PublicKey + owner: web3.PublicKey +} + +export const cancelRedeemInstructionDiscriminator = [ + 111, 76, 232, 50, 39, 175, 48, 242, +] + +/** + * Creates a _CancelRedeem_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category CancelRedeem + * @category generated + */ +export function createCancelRedeemInstruction( + accounts: CancelRedeemInstructionAccounts, + args: CancelRedeemInstructionArgs +) { + const { authority, gummyrollProgram, merkleSlab, voucher, owner } = accounts + + const [data] = cancelRedeemStruct.serialize({ + instructionDiscriminator: cancelRedeemInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: authority, + isWritable: false, + isSigner: false, + }, + { + pubkey: gummyrollProgram, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + { + pubkey: voucher, + isWritable: true, + isSigner: false, + }, + { + pubkey: owner, + isWritable: true, + isSigner: true, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/instructions/compress.ts b/contracts/sdk/bubblegum/src/generated/instructions/compress.ts new file mode 100644 index 00000000000..1888ae1943d --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/compress.ts @@ -0,0 +1,163 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as splToken from '@solana/spl-token' +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * @category Instructions + * @category Compress + * @category generated + */ +export const compressStruct = new beet.BeetArgsStruct<{ + instructionDiscriminator: number[] /* size: 8 */ +}>( + [['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)]], + 'CompressInstructionArgs' +) +/** + * Accounts required by the _compress_ instruction + * + * @property [] authority + * @property [] merkleSlab + * @property [**signer**] owner + * @property [] delegate + * @property [_writable_] tokenAccount + * @property [_writable_] mint + * @property [_writable_] metadata + * @property [_writable_] masterEdition + * @property [_writable_, **signer**] payer + * @property [] tokenMetadataProgram + * @property [] gummyrollProgram + * @category Instructions + * @category Compress + * @category generated + */ +export type CompressInstructionAccounts = { + authority: web3.PublicKey + merkleSlab: web3.PublicKey + owner: web3.PublicKey + delegate: web3.PublicKey + tokenAccount: web3.PublicKey + mint: web3.PublicKey + metadata: web3.PublicKey + masterEdition: web3.PublicKey + payer: web3.PublicKey + tokenMetadataProgram: web3.PublicKey + gummyrollProgram: web3.PublicKey +} + +export const compressInstructionDiscriminator = [ + 82, 193, 176, 117, 176, 21, 115, 253, +] + +/** + * Creates a _Compress_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @category Instructions + * @category Compress + * @category generated + */ +export function createCompressInstruction( + accounts: CompressInstructionAccounts +) { + const { + authority, + merkleSlab, + owner, + delegate, + tokenAccount, + mint, + metadata, + masterEdition, + payer, + tokenMetadataProgram, + gummyrollProgram, + } = accounts + + const [data] = compressStruct.serialize({ + instructionDiscriminator: compressInstructionDiscriminator, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: authority, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: false, + isSigner: false, + }, + { + pubkey: owner, + isWritable: false, + isSigner: true, + }, + { + pubkey: delegate, + isWritable: false, + isSigner: false, + }, + { + pubkey: tokenAccount, + isWritable: true, + isSigner: false, + }, + { + pubkey: mint, + isWritable: true, + isSigner: false, + }, + { + pubkey: metadata, + isWritable: true, + isSigner: false, + }, + { + pubkey: masterEdition, + isWritable: true, + isSigner: false, + }, + { + pubkey: payer, + isWritable: true, + isSigner: true, + }, + { + pubkey: web3.SystemProgram.programId, + isWritable: false, + isSigner: false, + }, + { + pubkey: tokenMetadataProgram, + isWritable: false, + isSigner: false, + }, + { + pubkey: splToken.TOKEN_PROGRAM_ID, + isWritable: false, + isSigner: false, + }, + { + pubkey: gummyrollProgram, + isWritable: false, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/instructions/createTree.ts b/contracts/sdk/bubblegum/src/generated/instructions/createTree.ts new file mode 100644 index 00000000000..f794dd828a2 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/createTree.ts @@ -0,0 +1,110 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * @category Instructions + * @category CreateTree + * @category generated + */ +export type CreateTreeInstructionArgs = { + maxDepth: number + maxBufferSize: number +} +/** + * @category Instructions + * @category CreateTree + * @category generated + */ +export const createTreeStruct = new beet.BeetArgsStruct< + CreateTreeInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['maxDepth', beet.u32], + ['maxBufferSize', beet.u32], + ], + 'CreateTreeInstructionArgs' +) +/** + * Accounts required by the _createTree_ instruction + * + * @property [**signer**] treeCreator + * @property [] authority + * @property [] gummyrollProgram + * @property [_writable_] merkleSlab + * @category Instructions + * @category CreateTree + * @category generated + */ +export type CreateTreeInstructionAccounts = { + treeCreator: web3.PublicKey + authority: web3.PublicKey + gummyrollProgram: web3.PublicKey + merkleSlab: web3.PublicKey +} + +export const createTreeInstructionDiscriminator = [ + 165, 83, 136, 142, 89, 202, 47, 220, +] + +/** + * Creates a _CreateTree_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category CreateTree + * @category generated + */ +export function createCreateTreeInstruction( + accounts: CreateTreeInstructionAccounts, + args: CreateTreeInstructionArgs +) { + const { treeCreator, authority, gummyrollProgram, merkleSlab } = accounts + + const [data] = createTreeStruct.serialize({ + instructionDiscriminator: createTreeInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: treeCreator, + isWritable: false, + isSigner: true, + }, + { + pubkey: authority, + isWritable: false, + isSigner: false, + }, + { + pubkey: gummyrollProgram, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/instructions/decompress.ts b/contracts/sdk/bubblegum/src/generated/instructions/decompress.ts new file mode 100644 index 00000000000..391b008711d --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/decompress.ts @@ -0,0 +1,173 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as splToken from '@solana/spl-token' +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' +import { MetadataArgs, metadataArgsBeet } from '../types/MetadataArgs' + +/** + * @category Instructions + * @category Decompress + * @category generated + */ +export type DecompressInstructionArgs = { + metadata: MetadataArgs +} +/** + * @category Instructions + * @category Decompress + * @category generated + */ +export const decompressStruct = new beet.FixableBeetArgsStruct< + DecompressInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['metadata', metadataArgsBeet], + ], + 'DecompressInstructionArgs' +) +/** + * Accounts required by the _decompress_ instruction + * + * @property [_writable_] voucher + * @property [_writable_, **signer**] owner + * @property [_writable_] tokenAccount + * @property [_writable_] mint + * @property [] mintAuthority + * @property [_writable_] metadata + * @property [_writable_] masterEdition + * @property [] sysvarRent + * @property [] tokenMetadataProgram + * @property [] associatedTokenProgram + * @category Instructions + * @category Decompress + * @category generated + */ +export type DecompressInstructionAccounts = { + voucher: web3.PublicKey + owner: web3.PublicKey + tokenAccount: web3.PublicKey + mint: web3.PublicKey + mintAuthority: web3.PublicKey + metadata: web3.PublicKey + masterEdition: web3.PublicKey + sysvarRent: web3.PublicKey + tokenMetadataProgram: web3.PublicKey + associatedTokenProgram: web3.PublicKey +} + +export const decompressInstructionDiscriminator = [ + 74, 60, 49, 197, 18, 110, 93, 154, +] + +/** + * Creates a _Decompress_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category Decompress + * @category generated + */ +export function createDecompressInstruction( + accounts: DecompressInstructionAccounts, + args: DecompressInstructionArgs +) { + const { + voucher, + owner, + tokenAccount, + mint, + mintAuthority, + metadata, + masterEdition, + sysvarRent, + tokenMetadataProgram, + associatedTokenProgram, + } = accounts + + const [data] = decompressStruct.serialize({ + instructionDiscriminator: decompressInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: voucher, + isWritable: true, + isSigner: false, + }, + { + pubkey: owner, + isWritable: true, + isSigner: true, + }, + { + pubkey: tokenAccount, + isWritable: true, + isSigner: false, + }, + { + pubkey: mint, + isWritable: true, + isSigner: false, + }, + { + pubkey: mintAuthority, + isWritable: false, + isSigner: false, + }, + { + pubkey: metadata, + isWritable: true, + isSigner: false, + }, + { + pubkey: masterEdition, + isWritable: true, + isSigner: false, + }, + { + pubkey: web3.SystemProgram.programId, + isWritable: false, + isSigner: false, + }, + { + pubkey: sysvarRent, + isWritable: false, + isSigner: false, + }, + { + pubkey: tokenMetadataProgram, + isWritable: false, + isSigner: false, + }, + { + pubkey: splToken.TOKEN_PROGRAM_ID, + isWritable: false, + isSigner: false, + }, + { + pubkey: associatedTokenProgram, + isWritable: false, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/instructions/delegate.ts b/contracts/sdk/bubblegum/src/generated/instructions/delegate.ts new file mode 100644 index 00000000000..adf9ca68bc8 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/delegate.ts @@ -0,0 +1,140 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' +import { Version, versionBeet } from '../types/Version' + +/** + * @category Instructions + * @category Delegate + * @category generated + */ +export type DelegateInstructionArgs = { + version: Version + root: number[] /* size: 32 */ + dataHash: number[] /* size: 32 */ + creatorHash: number[] /* size: 32 */ + nonce: beet.bignum + index: number +} +/** + * @category Instructions + * @category Delegate + * @category generated + */ +export const delegateStruct = new beet.BeetArgsStruct< + DelegateInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['version', versionBeet], + ['root', beet.uniformFixedSizeArray(beet.u8, 32)], + ['dataHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ['creatorHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ['nonce', beet.u128], + ['index', beet.u32], + ], + 'DelegateInstructionArgs' +) +/** + * Accounts required by the _delegate_ instruction + * + * @property [] authority + * @property [**signer**] owner + * @property [] previousDelegate + * @property [] newDelegate + * @property [] gummyrollProgram + * @property [_writable_] merkleSlab + * @category Instructions + * @category Delegate + * @category generated + */ +export type DelegateInstructionAccounts = { + authority: web3.PublicKey + owner: web3.PublicKey + previousDelegate: web3.PublicKey + newDelegate: web3.PublicKey + gummyrollProgram: web3.PublicKey + merkleSlab: web3.PublicKey +} + +export const delegateInstructionDiscriminator = [ + 90, 147, 75, 178, 85, 88, 4, 137, +] + +/** + * Creates a _Delegate_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category Delegate + * @category generated + */ +export function createDelegateInstruction( + accounts: DelegateInstructionAccounts, + args: DelegateInstructionArgs +) { + const { + authority, + owner, + previousDelegate, + newDelegate, + gummyrollProgram, + merkleSlab, + } = accounts + + const [data] = delegateStruct.serialize({ + instructionDiscriminator: delegateInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: authority, + isWritable: false, + isSigner: false, + }, + { + pubkey: owner, + isWritable: false, + isSigner: true, + }, + { + pubkey: previousDelegate, + isWritable: false, + isSigner: false, + }, + { + pubkey: newDelegate, + isWritable: false, + isSigner: false, + }, + { + pubkey: gummyrollProgram, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/instructions/index.ts b/contracts/sdk/bubblegum/src/generated/instructions/index.ts new file mode 100644 index 00000000000..2ba9192b72c --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/index.ts @@ -0,0 +1,10 @@ +export * from './burn' +export * from './cancelRedeem' +export * from './compress' +export * from './createTree' +export * from './decompress' +export * from './delegate' +export * from './initializeNonce' +export * from './mint' +export * from './redeem' +export * from './transfer' diff --git a/contracts/sdk/bubblegum/src/generated/instructions/initializeNonce.ts b/contracts/sdk/bubblegum/src/generated/instructions/initializeNonce.ts new file mode 100644 index 00000000000..bde9fbd1e24 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/initializeNonce.ts @@ -0,0 +1,82 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * @category Instructions + * @category InitializeNonce + * @category generated + */ +export const initializeNonceStruct = new beet.BeetArgsStruct<{ + instructionDiscriminator: number[] /* size: 8 */ +}>( + [['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)]], + 'InitializeNonceInstructionArgs' +) +/** + * Accounts required by the _initializeNonce_ instruction + * + * @property [_writable_] nonce + * @property [_writable_, **signer**] payer + * @category Instructions + * @category InitializeNonce + * @category generated + */ +export type InitializeNonceInstructionAccounts = { + nonce: web3.PublicKey + payer: web3.PublicKey +} + +export const initializeNonceInstructionDiscriminator = [ + 64, 206, 214, 231, 20, 15, 231, 41, +] + +/** + * Creates a _InitializeNonce_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @category Instructions + * @category InitializeNonce + * @category generated + */ +export function createInitializeNonceInstruction( + accounts: InitializeNonceInstructionAccounts +) { + const { nonce, payer } = accounts + + const [data] = initializeNonceStruct.serialize({ + instructionDiscriminator: initializeNonceInstructionDiscriminator, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: nonce, + isWritable: true, + isSigner: false, + }, + { + pubkey: payer, + isWritable: true, + isSigner: true, + }, + { + pubkey: web3.SystemProgram.programId, + isWritable: false, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/instructions/mint.ts b/contracts/sdk/bubblegum/src/generated/instructions/mint.ts new file mode 100644 index 00000000000..51cdc2a0d3b --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/mint.ts @@ -0,0 +1,141 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' +import { Version, versionBeet } from '../types/Version' +import { MetadataArgs, metadataArgsBeet } from '../types/MetadataArgs' + +/** + * @category Instructions + * @category Mint + * @category generated + */ +export type MintInstructionArgs = { + version: Version + message: MetadataArgs +} +/** + * @category Instructions + * @category Mint + * @category generated + */ +export const mintStruct = new beet.FixableBeetArgsStruct< + MintInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['version', versionBeet], + ['message', metadataArgsBeet], + ], + 'MintInstructionArgs' +) +/** + * Accounts required by the _mint_ instruction + * + * @property [**signer**] mintAuthority + * @property [] authority + * @property [_writable_] nonce + * @property [] gummyrollProgram + * @property [**signer**] owner + * @property [] delegate + * @property [_writable_] merkleSlab + * @category Instructions + * @category Mint + * @category generated + */ +export type MintInstructionAccounts = { + mintAuthority: web3.PublicKey + authority: web3.PublicKey + nonce: web3.PublicKey + gummyrollProgram: web3.PublicKey + owner: web3.PublicKey + delegate: web3.PublicKey + merkleSlab: web3.PublicKey +} + +export const mintInstructionDiscriminator = [ + 51, 57, 225, 47, 182, 146, 137, 166, +] + +/** + * Creates a _Mint_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category Mint + * @category generated + */ +export function createMintInstruction( + accounts: MintInstructionAccounts, + args: MintInstructionArgs +) { + const { + mintAuthority, + authority, + nonce, + gummyrollProgram, + owner, + delegate, + merkleSlab, + } = accounts + + const [data] = mintStruct.serialize({ + instructionDiscriminator: mintInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: mintAuthority, + isWritable: false, + isSigner: true, + }, + { + pubkey: authority, + isWritable: false, + isSigner: false, + }, + { + pubkey: nonce, + isWritable: true, + isSigner: false, + }, + { + pubkey: gummyrollProgram, + isWritable: false, + isSigner: false, + }, + { + pubkey: owner, + isWritable: false, + isSigner: true, + }, + { + pubkey: delegate, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/instructions/redeem.ts b/contracts/sdk/bubblegum/src/generated/instructions/redeem.ts new file mode 100644 index 00000000000..d7dc5342e8a --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/redeem.ts @@ -0,0 +1,139 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' +import { Version, versionBeet } from '../types/Version' + +/** + * @category Instructions + * @category Redeem + * @category generated + */ +export type RedeemInstructionArgs = { + version: Version + root: number[] /* size: 32 */ + dataHash: number[] /* size: 32 */ + creatorHash: number[] /* size: 32 */ + nonce: beet.bignum + index: number +} +/** + * @category Instructions + * @category Redeem + * @category generated + */ +export const redeemStruct = new beet.BeetArgsStruct< + RedeemInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['version', versionBeet], + ['root', beet.uniformFixedSizeArray(beet.u8, 32)], + ['dataHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ['creatorHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ['nonce', beet.u128], + ['index', beet.u32], + ], + 'RedeemInstructionArgs' +) +/** + * Accounts required by the _redeem_ instruction + * + * @property [] authority + * @property [] gummyrollProgram + * @property [_writable_, **signer**] owner + * @property [] delegate + * @property [_writable_] merkleSlab + * @property [_writable_] voucher + * @category Instructions + * @category Redeem + * @category generated + */ +export type RedeemInstructionAccounts = { + authority: web3.PublicKey + gummyrollProgram: web3.PublicKey + owner: web3.PublicKey + delegate: web3.PublicKey + merkleSlab: web3.PublicKey + voucher: web3.PublicKey +} + +export const redeemInstructionDiscriminator = [ + 184, 12, 86, 149, 70, 196, 97, 225, +] + +/** + * Creates a _Redeem_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category Redeem + * @category generated + */ +export function createRedeemInstruction( + accounts: RedeemInstructionAccounts, + args: RedeemInstructionArgs +) { + const { authority, gummyrollProgram, owner, delegate, merkleSlab, voucher } = + accounts + + const [data] = redeemStruct.serialize({ + instructionDiscriminator: redeemInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: authority, + isWritable: false, + isSigner: false, + }, + { + pubkey: gummyrollProgram, + isWritable: false, + isSigner: false, + }, + { + pubkey: owner, + isWritable: true, + isSigner: true, + }, + { + pubkey: delegate, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + { + pubkey: voucher, + isWritable: true, + isSigner: false, + }, + { + pubkey: web3.SystemProgram.programId, + isWritable: false, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/instructions/transfer.ts b/contracts/sdk/bubblegum/src/generated/instructions/transfer.ts new file mode 100644 index 00000000000..45ca7f57d49 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/instructions/transfer.ts @@ -0,0 +1,134 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' +import { Version, versionBeet } from '../types/Version' + +/** + * @category Instructions + * @category Transfer + * @category generated + */ +export type TransferInstructionArgs = { + version: Version + root: number[] /* size: 32 */ + dataHash: number[] /* size: 32 */ + creatorHash: number[] /* size: 32 */ + nonce: beet.bignum + index: number +} +/** + * @category Instructions + * @category Transfer + * @category generated + */ +export const transferStruct = new beet.BeetArgsStruct< + TransferInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['version', versionBeet], + ['root', beet.uniformFixedSizeArray(beet.u8, 32)], + ['dataHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ['creatorHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ['nonce', beet.u128], + ['index', beet.u32], + ], + 'TransferInstructionArgs' +) +/** + * Accounts required by the _transfer_ instruction + * + * @property [] authority + * @property [] owner + * @property [] delegate + * @property [] newOwner + * @property [] gummyrollProgram + * @property [_writable_] merkleSlab + * @category Instructions + * @category Transfer + * @category generated + */ +export type TransferInstructionAccounts = { + authority: web3.PublicKey + owner: web3.PublicKey + delegate: web3.PublicKey + newOwner: web3.PublicKey + gummyrollProgram: web3.PublicKey + merkleSlab: web3.PublicKey +} + +export const transferInstructionDiscriminator = [ + 163, 52, 200, 231, 140, 3, 69, 186, +] + +/** + * Creates a _Transfer_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category Transfer + * @category generated + */ +export function createTransferInstruction( + accounts: TransferInstructionAccounts, + args: TransferInstructionArgs +) { + const { authority, owner, delegate, newOwner, gummyrollProgram, merkleSlab } = + accounts + + const [data] = transferStruct.serialize({ + instructionDiscriminator: transferInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: authority, + isWritable: false, + isSigner: false, + }, + { + pubkey: owner, + isWritable: false, + isSigner: false, + }, + { + pubkey: delegate, + isWritable: false, + isSigner: false, + }, + { + pubkey: newOwner, + isWritable: false, + isSigner: false, + }, + { + pubkey: gummyrollProgram, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BGUMzZr2wWfD2yzrXFEWTK2HbdYhqQCP2EZoPEkZBD6o' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/bubblegum/src/generated/types/Collection.ts b/contracts/sdk/bubblegum/src/generated/types/Collection.ts new file mode 100644 index 00000000000..f7402e06465 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/Collection.ts @@ -0,0 +1,26 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as web3 from '@solana/web3.js' +import * as beet from '@metaplex-foundation/beet' +import * as beetSolana from '@metaplex-foundation/beet-solana' +export type Collection = { + verified: boolean + key: web3.PublicKey +} + +/** + * @category userTypes + * @category generated + */ +export const collectionBeet = new beet.BeetArgsStruct( + [ + ['verified', beet.bool], + ['key', beetSolana.publicKey], + ], + 'Collection' +) diff --git a/contracts/sdk/bubblegum/src/generated/types/Creator.ts b/contracts/sdk/bubblegum/src/generated/types/Creator.ts new file mode 100644 index 00000000000..59ef0eb0d64 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/Creator.ts @@ -0,0 +1,28 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as web3 from '@solana/web3.js' +import * as beetSolana from '@metaplex-foundation/beet-solana' +import * as beet from '@metaplex-foundation/beet' +export type Creator = { + address: web3.PublicKey + verified: boolean + share: number +} + +/** + * @category userTypes + * @category generated + */ +export const creatorBeet = new beet.BeetArgsStruct( + [ + ['address', beetSolana.publicKey], + ['verified', beet.bool], + ['share', beet.u8], + ], + 'Creator' +) diff --git a/contracts/sdk/bubblegum/src/generated/types/InstructionName.ts b/contracts/sdk/bubblegum/src/generated/types/InstructionName.ts new file mode 100644 index 00000000000..1c528f8a3b8 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/InstructionName.ts @@ -0,0 +1,29 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +/** + * @category enums + * @category generated + */ +export enum InstructionName { + Unknown, + Mint, + Redeem, + CancelRedeem, + Transfer, + Delegate, + Decompress, +} + +/** + * @category userTypes + * @category generated + */ +export const instructionNameBeet = beet.fixedScalarEnum( + InstructionName +) as beet.FixedSizeBeet diff --git a/contracts/sdk/bubblegum/src/generated/types/LeafSchema.ts b/contracts/sdk/bubblegum/src/generated/types/LeafSchema.ts new file mode 100644 index 00000000000..87f75f5dccd --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/LeafSchema.ts @@ -0,0 +1,35 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as web3 from '@solana/web3.js' +import * as beet from '@metaplex-foundation/beet' +import * as beetSolana from '@metaplex-foundation/beet-solana' +import { Version, versionBeet } from './Version' +export type LeafSchema = { + version: Version + owner: web3.PublicKey + delegate: web3.PublicKey + nonce: beet.bignum + dataHash: number[] /* size: 32 */ + creatorHash: number[] /* size: 32 */ +} + +/** + * @category userTypes + * @category generated + */ +export const leafSchemaBeet = new beet.BeetArgsStruct( + [ + ['version', versionBeet], + ['owner', beetSolana.publicKey], + ['delegate', beetSolana.publicKey], + ['nonce', beet.u128], + ['dataHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ['creatorHash', beet.uniformFixedSizeArray(beet.u8, 32)], + ], + 'LeafSchema' +) diff --git a/contracts/sdk/bubblegum/src/generated/types/MetadataArgs.ts b/contracts/sdk/bubblegum/src/generated/types/MetadataArgs.ts new file mode 100644 index 00000000000..cf5c41ea17b --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/MetadataArgs.ts @@ -0,0 +1,52 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import { TokenStandard, tokenStandardBeet } from './TokenStandard' +import { Collection, collectionBeet } from './Collection' +import { Uses, usesBeet } from './Uses' +import { + TokenProgramVersion, + tokenProgramVersionBeet, +} from './TokenProgramVersion' +import { Creator, creatorBeet } from './Creator' +export type MetadataArgs = { + name: string + symbol: string + uri: string + sellerFeeBasisPoints: number + primarySaleHappened: boolean + isMutable: boolean + editionNonce: beet.COption + tokenStandard: beet.COption + collection: beet.COption + uses: beet.COption + tokenProgramVersion: TokenProgramVersion + creators: Creator[] +} + +/** + * @category userTypes + * @category generated + */ +export const metadataArgsBeet = new beet.FixableBeetArgsStruct( + [ + ['name', beet.utf8String], + ['symbol', beet.utf8String], + ['uri', beet.utf8String], + ['sellerFeeBasisPoints', beet.u16], + ['primarySaleHappened', beet.bool], + ['isMutable', beet.bool], + ['editionNonce', beet.coption(beet.u8)], + ['tokenStandard', beet.coption(tokenStandardBeet)], + ['collection', beet.coption(collectionBeet)], + ['uses', beet.coption(usesBeet)], + ['tokenProgramVersion', tokenProgramVersionBeet], + ['creators', beet.array(creatorBeet)], + ], + 'MetadataArgs' +) diff --git a/contracts/sdk/bubblegum/src/generated/types/TokenProgramVersion.ts b/contracts/sdk/bubblegum/src/generated/types/TokenProgramVersion.ts new file mode 100644 index 00000000000..3da19eb29cb --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/TokenProgramVersion.ts @@ -0,0 +1,24 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +/** + * @category enums + * @category generated + */ +export enum TokenProgramVersion { + Original, + Token2022, +} + +/** + * @category userTypes + * @category generated + */ +export const tokenProgramVersionBeet = beet.fixedScalarEnum( + TokenProgramVersion +) as beet.FixedSizeBeet diff --git a/contracts/sdk/bubblegum/src/generated/types/TokenStandard.ts b/contracts/sdk/bubblegum/src/generated/types/TokenStandard.ts new file mode 100644 index 00000000000..0dddfc94e68 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/TokenStandard.ts @@ -0,0 +1,26 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +/** + * @category enums + * @category generated + */ +export enum TokenStandard { + NonFungible, + FungibleAsset, + Fungible, + NonFungibleEdition, +} + +/** + * @category userTypes + * @category generated + */ +export const tokenStandardBeet = beet.fixedScalarEnum( + TokenStandard +) as beet.FixedSizeBeet diff --git a/contracts/sdk/bubblegum/src/generated/types/UseMethod.ts b/contracts/sdk/bubblegum/src/generated/types/UseMethod.ts new file mode 100644 index 00000000000..3c26540cea1 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/UseMethod.ts @@ -0,0 +1,25 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +/** + * @category enums + * @category generated + */ +export enum UseMethod { + Burn, + Multiple, + Single, +} + +/** + * @category userTypes + * @category generated + */ +export const useMethodBeet = beet.fixedScalarEnum( + UseMethod +) as beet.FixedSizeBeet diff --git a/contracts/sdk/bubblegum/src/generated/types/Uses.ts b/contracts/sdk/bubblegum/src/generated/types/Uses.ts new file mode 100644 index 00000000000..ee3dc2a2de9 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/Uses.ts @@ -0,0 +1,27 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import { UseMethod, useMethodBeet } from './UseMethod' +export type Uses = { + useMethod: UseMethod + remaining: beet.bignum + total: beet.bignum +} + +/** + * @category userTypes + * @category generated + */ +export const usesBeet = new beet.BeetArgsStruct( + [ + ['useMethod', useMethodBeet], + ['remaining', beet.u64], + ['total', beet.u64], + ], + 'Uses' +) diff --git a/contracts/sdk/bubblegum/src/generated/types/Version.ts b/contracts/sdk/bubblegum/src/generated/types/Version.ts new file mode 100644 index 00000000000..f764dee8a07 --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/Version.ts @@ -0,0 +1,24 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +/** + * @category enums + * @category generated + */ +export enum Version { + V0, +} + +/** + * @category userTypes + * @category generated + */ +export const versionBeet = beet.fixedScalarEnum(Version) as beet.FixedSizeBeet< + Version, + Version +> diff --git a/contracts/sdk/bubblegum/src/generated/types/index.ts b/contracts/sdk/bubblegum/src/generated/types/index.ts new file mode 100644 index 00000000000..bde249071ee --- /dev/null +++ b/contracts/sdk/bubblegum/src/generated/types/index.ts @@ -0,0 +1,10 @@ +export * from './Collection' +export * from './Creator' +export * from './InstructionName' +export * from './LeafSchema' +export * from './MetadataArgs' +export * from './TokenProgramVersion' +export * from './TokenStandard' +export * from './UseMethod' +export * from './Uses' +export * from './Version' From d8cc98df039c1c9618489e18b59ce0ce6f9ebcfa Mon Sep 17 00:00:00 2001 From: Noah Gundotra Date: Mon, 6 Jun 2022 10:29:50 -0700 Subject: [PATCH 2/8] update tests to use solita SDK --- contracts/tests/bubblegum-test.ts | 244 ++++++++++++++++-------------- contracts/yarn.lock | 102 +++++++++++-- 2 files changed, 221 insertions(+), 125 deletions(-) diff --git a/contracts/tests/bubblegum-test.ts b/contracts/tests/bubblegum-test.ts index 611328b0d21..fcc32b6685a 100644 --- a/contracts/tests/bubblegum-test.ts +++ b/contracts/tests/bubblegum-test.ts @@ -13,12 +13,21 @@ import { SYSVAR_RENT_PUBKEY, } from "@solana/web3.js"; import { assert } from "chai"; +import { + createMintInstruction, + createDecompressInstruction, + createTransferInstruction, + createDelegateInstruction, + createRedeemInstruction, + createCancelRedeemInstruction +} from '../sdk/bubblegum/src/generated/instructions'; import { buildTree, Tree } from "./merkle-tree"; import { decodeMerkleRoll, getMerkleRollAccountSize, assertOnChainMerkleRollProperties, + createTransferAuthorityIx, } from "../sdk/gummyroll"; import NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet"; import { @@ -26,13 +35,25 @@ import { TOKEN_PROGRAM_ID, Token } from "@solana/spl-token"; -import { logTx } from "./utils"; +import { execute, logTx } from "./utils"; +import { createMint } from "../../deps/solana-program-library/token/js/src"; +import { TokenProgramVersion, Version } from "../sdk/bubblegum/src/generated"; +import { createTransferAuthorityInstruction } from "../sdk/solita/gummyroll/src/generated"; // @ts-ignore let Bubblegum; // @ts-ignore let GummyrollProgramId; +/// Converts to Uint8Array +function bufferToArray(buffer: Buffer): number[] { + const nums = []; + for (let i = 0; i < buffer.length; i++) { + nums.push(buffer.at(i)); + } + return nums; +} + describe("bubblegum", () => { // Configure the client to use the local cluster. let offChainTree: Tree; @@ -149,7 +170,7 @@ describe("bubblegum", () => { await Bubblegum.provider.send(tx, [payer, merkleRollKeypair], { commitment: "confirmed", }); - + await assertOnChainMerkleRollProperties(Bubblegum.provider.connection, MAX_DEPTH, MAX_SIZE, authority, new PublicKey(tree.root), merkleRollKeypair.publicKey); return [merkleRollKeypair, tree, authority, nonce]; @@ -178,26 +199,21 @@ describe("bubblegum", () => { isMutable: false, editionNonce: null, tokenStandard: null, - tokenProgramVersion: { - original: {}, - }, + tokenProgramVersion: TokenProgramVersion.Original, collection: null, uses: null, creators: [], }; - let version = { v0: {} }; - let mintIx = await Bubblegum.instruction.mint(version, metadata, { - accounts: { - mintAuthority: payer.publicKey, - authority: treeAuthority, - nonce: nonceAccount, - gummyrollProgram: GummyrollProgramId, - owner: payer.publicKey, - delegate: payer.publicKey, - merkleSlab: merkleRollKeypair.publicKey, - }, - signers: [payer], - }); + let version = Version.V0; + const mintIx = createMintInstruction({ + mintAuthority: payer.publicKey, + authority: treeAuthority, + nonce: nonceAccount, + gummyrollProgram: GummyrollProgramId, + owner: payer.publicKey, + delegate: payer.publicKey, + merkleSlab: merkleRollKeypair.publicKey, + }, { version, message: metadata }); console.log(" - Minting to tree"); const mintTx = await Bubblegum.provider.send( new Transaction().add(mintIx), @@ -207,8 +223,8 @@ describe("bubblegum", () => { commitment: "confirmed", } ); - const leafHash = Buffer.from(keccak_256.digest(mintIx.data.slice(9))); - const creatorHash = Buffer.from(keccak_256.digest([])); + const dataHash = bufferToArray(Buffer.from(keccak_256.digest(mintIx.data.slice(9)))); + const creatorHash = bufferToArray(Buffer.from(keccak_256.digest([]))); let merkleRollAccount = await Bubblegum.provider.connection.getAccountInfo( merkleRollKeypair.publicKey @@ -220,25 +236,25 @@ describe("bubblegum", () => { console.log(" - Transferring Ownership"); const nonceInfo = await (Bubblegum.provider.connection as web3Connection).getAccountInfo(nonceAccount); const leafNonce = (new BN(nonceInfo.data.slice(8, 24), "le")).sub(new BN(1)); - let transferTx = await Bubblegum.rpc.transfer( - version, - onChainRoot, - leafHash, - creatorHash, - leafNonce, - 0, + let transferIx = createTransferInstruction( { - accounts: { - authority: treeAuthority, - owner: payer.publicKey, - delegate: payer.publicKey, - newOwner: destination.publicKey, - gummyrollProgram: GummyrollProgramId, - merkleSlab: merkleRollKeypair.publicKey, - }, - signers: [payer], + authority: treeAuthority, + owner: payer.publicKey, + delegate: payer.publicKey, + newOwner: destination.publicKey, + gummyrollProgram: GummyrollProgramId, + merkleSlab: merkleRollKeypair.publicKey, + }, + { + version, + root: bufferToArray(onChainRoot), + dataHash, + creatorHash, + nonce: leafNonce, + index: 0, } ); + await execute(Bubblegum.provider, [transferIx], [payer]) merkleRollAccount = await Bubblegum.provider.connection.getAccountInfo( merkleRollKeypair.publicKey @@ -248,25 +264,25 @@ describe("bubblegum", () => { merkleRoll.roll.changeLogs[merkleRoll.roll.activeIndex].root.toBuffer(); console.log(" - Delegating Ownership"); - let delegateTx = await Bubblegum.rpc.delegate( - version, - onChainRoot, - leafHash, - creatorHash, - leafNonce, - 0, + let delegateIx = await createDelegateInstruction( { - accounts: { - authority: treeAuthority, - owner: destination.publicKey, - previousDelegate: destination.publicKey, - newDelegate: delegateKey.publicKey, - gummyrollProgram: GummyrollProgramId, - merkleSlab: merkleRollKeypair.publicKey, - }, - signers: [destination], + authority: treeAuthority, + owner: destination.publicKey, + previousDelegate: destination.publicKey, + newDelegate: delegateKey.publicKey, + gummyrollProgram: GummyrollProgramId, + merkleSlab: merkleRollKeypair.publicKey, + }, + { + version, + root: bufferToArray(onChainRoot), + dataHash, + creatorHash, + nonce: leafNonce, + index: 0, } ); + await execute(Bubblegum.provider, [delegateIx], [destination]); merkleRollAccount = await Bubblegum.provider.connection.getAccountInfo( merkleRollKeypair.publicKey @@ -276,23 +292,21 @@ describe("bubblegum", () => { merkleRoll.roll.changeLogs[merkleRoll.roll.activeIndex].root.toBuffer(); console.log(" - Transferring Ownership (through delegate)"); - let delTransferIx = await Bubblegum.instruction.transfer( - version, - onChainRoot, - leafHash, - creatorHash, - leafNonce, - 0, + let delTransferIx = createTransferInstruction({ + authority: treeAuthority, + owner: destination.publicKey, + delegate: delegateKey.publicKey, + newOwner: payer.publicKey, + gummyrollProgram: GummyrollProgramId, + merkleSlab: merkleRollKeypair.publicKey, + }, { - accounts: { - authority: treeAuthority, - owner: destination.publicKey, - delegate: delegateKey.publicKey, - newOwner: payer.publicKey, - gummyrollProgram: GummyrollProgramId, - merkleSlab: merkleRollKeypair.publicKey, - }, - signers: [delegateKey], + version, + root: bufferToArray(onChainRoot), + dataHash, + creatorHash, + nonce: leafNonce, + index: 0, } ); delTransferIx.keys[2].isSigner = true; @@ -317,24 +331,22 @@ describe("bubblegum", () => { ); console.log(" - Redeeming Leaf", voucher.toBase58()); - let redeemIx = await Bubblegum.instruction.redeem( - version, - onChainRoot, - leafHash, - creatorHash, - leafNonce, - 0, + let redeemIx = createRedeemInstruction( { - accounts: { - authority: treeAuthority, - owner: payer.publicKey, - delegate: payer.publicKey, - gummyrollProgram: GummyrollProgramId, - merkleSlab: merkleRollKeypair.publicKey, - voucher: voucher, - systemProgram: SystemProgram.programId, - }, - signers: [payer], + authority: treeAuthority, + owner: payer.publicKey, + delegate: payer.publicKey, + gummyrollProgram: GummyrollProgramId, + merkleSlab: merkleRollKeypair.publicKey, + voucher: voucher, + }, + { + version, + root: bufferToArray(onChainRoot), + dataHash, + creatorHash, + nonce: leafNonce, + index: 0, } ); let redeemTx = await Bubblegum.provider.send( @@ -345,20 +357,20 @@ describe("bubblegum", () => { } ); console.log(" - Cancelling redeem (reinserting to tree)"); - let cancelRedeemIx = await Bubblegum.instruction.cancelRedeem( - onChainRoot, + + const cancelRedeemIx = createCancelRedeemInstruction( { - accounts: { - authority: treeAuthority, - owner: payer.publicKey, - delegate: payer.publicKey, - gummyrollProgram: GummyrollProgramId, - merkleSlab: merkleRollKeypair.publicKey, - voucher: voucher, - }, - signers: [payer], + authority: treeAuthority, + owner: payer.publicKey, + gummyrollProgram: GummyrollProgramId, + merkleSlab: merkleRollKeypair.publicKey, + voucher: voucher, + }, + { + root: bufferToArray(onChainRoot) } - ); + + ) let cancelRedeemTx = await Bubblegum.provider.send( new Transaction().add(cancelRedeemIx), [payer], @@ -368,26 +380,26 @@ describe("bubblegum", () => { ); console.log(" - Decompressing leaf"); - redeemIx = await Bubblegum.instruction.redeem( - version, - onChainRoot, - leafHash, - creatorHash, - leafNonce, - 0, - { - accounts: { + + redeemIx = + createRedeemInstruction( + { authority: treeAuthority, owner: payer.publicKey, delegate: payer.publicKey, gummyrollProgram: GummyrollProgramId, merkleSlab: merkleRollKeypair.publicKey, voucher: voucher, - systemProgram: SystemProgram.programId, }, - signers: [payer], - } - ); + { + version, + root: bufferToArray(onChainRoot), + dataHash, + creatorHash, + nonce: leafNonce, + index: 0, + } + ) redeemTx = await Bubblegum.provider.send( new Transaction().add(redeemIx), [payer], @@ -431,8 +443,8 @@ describe("bubblegum", () => { )[0]; }; - let decompressIx = await Bubblegum.instruction.decompress(metadata, { - accounts: { + let decompressIx = createDecompressInstruction( + { voucher: voucher, owner: payer.publicKey, tokenAccount: await Token.getAssociatedTokenAddress( @@ -445,14 +457,14 @@ describe("bubblegum", () => { mintAuthority: mintAuthority, metadata: await getMetadata(tokenMint.publicKey), masterEdition: await getMasterEdition(tokenMint.publicKey), - systemProgram: SystemProgram.programId, sysvarRent: SYSVAR_RENT_PUBKEY, tokenMetadataProgram: PROGRAM_ID, - tokenProgram: TOKEN_PROGRAM_ID, associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, }, - signers: [payer], - }); + { + metadata, + } + ); decompressIx.keys[3].isSigner = true; let decompressTx = await Bubblegum.provider.send( diff --git a/contracts/yarn.lock b/contracts/yarn.lock index 669b7bd812d..b577fa72637 100644 --- a/contracts/yarn.lock +++ b/contracts/yarn.lock @@ -69,7 +69,7 @@ "@metaplex-foundation/beet" ">=0.1.0" "@solana/web3.js" "^1.31.0" -"@metaplex-foundation/beet@>=0.1.0": +"@metaplex-foundation/beet@>=0.1.0", "@metaplex-foundation/beet@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.2.0.tgz#e543e17fd1c4dc1251e9aea481a7429bc73f70b8" integrity sha512-H570hkJxmx/FxET1OggPPLkPL7psYQa71rNI9NJjYRM8WXdrEvmI/IRIEUW2KR6RqwWWN3FvlRHnKoQUV/lQtA== @@ -113,6 +113,32 @@ bn.js "^5.2.0" debug "^4.3.3" +"@metaplex-foundation/rustbin@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/rustbin/-/rustbin-0.3.1.tgz#bbcd61e8699b73c0b062728c6f5e8d52e8145042" + integrity sha512-hWd2JPrnt2/nJzkBpZD3Y6ZfCUlJujv2K7qUfsxdS0jSwLrSrOvYwmNWFw6mc3lbULj6VP4WDyuy9W5/CHU/lQ== + dependencies: + debug "^4.3.3" + semver "^7.3.7" + text-table "^0.2.0" + toml "^3.0.0" + +"@metaplex-foundation/solita@^0.8.2": + version "0.8.2" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/solita/-/solita-0.8.2.tgz#09674105be58aea7c76b31fd1d9888866c0e0203" + integrity sha512-YCypBul8CMnm6YeVR9GRJQiCRrnWdYAYcx50v7rz7gn+XdhSVLv1daQNwx8gBfYJtKYWAu9aVTp5SKw8dynCxQ== + dependencies: + "@metaplex-foundation/beet" "^0.2.0" + "@metaplex-foundation/beet-solana" "^0.1.1" + "@metaplex-foundation/rustbin" "^0.3.0" + "@solana/web3.js" "^1.36.0" + camelcase "^6.2.1" + debug "^4.3.3" + js-sha256 "^0.9.0" + prettier "^2.5.1" + snake-case "^3.0.4" + spok "^1.4.3" + "@project-serum/anchor@^0.21.0": version "0.21.0" resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.21.0.tgz#ad5fb33744991ec1900cdb2fd22707c908b12b5f" @@ -287,6 +313,28 @@ superstruct "^0.14.2" tweetnacl "^1.0.0" +"@solana/web3.js@^1.36.0": + version "1.43.4" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.43.4.tgz#cb38e3e3fe1195195017d5e5453ecced6cffc259" + integrity sha512-9+c965R3vjIRIfUFQtKfaG8BM4tVoo/fp4DvmqHAGLTaeHilVsRdyXszW6+Ues5KczgBejlp62k2SeUcbOibUg== + dependencies: + "@babel/runtime" "^7.12.5" + "@ethersproject/sha2" "^5.5.0" + "@solana/buffer-layout" "^4.0.0" + bigint-buffer "^1.1.5" + bn.js "^5.0.0" + borsh "^0.7.0" + bs58 "^4.0.1" + buffer "6.0.1" + fast-stable-stringify "^1.0.0" + jayson "^3.4.4" + js-sha3 "^0.8.0" + node-fetch "2" + rpc-websockets "^7.4.2" + secp256k1 "^4.0.2" + superstruct "^0.14.2" + tweetnacl "^1.0.0" + "@solana/web3.js@^1.37.0": version "1.37.0" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.37.0.tgz#167b5b5d4aedc151237d9230b6142da068b0af34" @@ -407,7 +455,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansicolors@^0.3.2: +ansicolors@^0.3.2, ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= @@ -594,7 +642,7 @@ camelcase@^5.3.1: resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: +camelcase@^6.0.0, camelcase@^6.2.1: version "6.3.0" resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -1163,6 +1211,13 @@ lower-case@^2.0.2: dependencies: tslib "^2.0.3" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + make-error@^1.1.1: version "1.3.6" resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" @@ -1270,18 +1325,18 @@ node-addon-api@^2.0.0: resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== -node-fetch@2.6.1: - version "2.6.1" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== - -node-fetch@2.6.7: +node-fetch@2, node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: version "4.3.0" resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz" @@ -1364,6 +1419,11 @@ picomatch@^2.0.4, picomatch@^2.2.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +prettier@^2.5.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" + integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== + ps-tree@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" @@ -1437,6 +1497,13 @@ secp256k1@^4.0.2: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" +semver@^7.3.7: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" @@ -1494,6 +1561,13 @@ split@0.3: dependencies: through "2" +spok@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/spok/-/spok-1.4.3.tgz#8516234e6bd8caf0e10567bd675e15fd03b5ceb8" + integrity sha512-5wFGctwrk638aDs+44u99kohxFNByUq2wo0uShQ9yqxSmsxqx7zKbMo1Busy4s7stZQXU+PhJ/BlVf2XWFEGIw== + dependencies: + ansicolors "~0.3.2" + start-server-and-test@^1.14.0: version "1.14.0" resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.14.0.tgz#c57f04f73eac15dd51733b551d775b40837fdde3" @@ -1569,6 +1643,11 @@ text-encoding-utf-8@^1.0.2: resolved "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz" integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + through@2, "through@>=2.2.7 <3", through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" @@ -1742,6 +1821,11 @@ y18n@^5.0.5: resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" From 9fa0990b12e6b7405dc76a4b68385887bf0efd7d Mon Sep 17 00:00:00 2001 From: Noah Gundotra Date: Mon, 6 Jun 2022 10:33:36 -0700 Subject: [PATCH 3/8] add readme --- contracts/sdk/bubblegum/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 contracts/sdk/bubblegum/README.md diff --git a/contracts/sdk/bubblegum/README.md b/contracts/sdk/bubblegum/README.md new file mode 100644 index 00000000000..3a02e6e7ec9 --- /dev/null +++ b/contracts/sdk/bubblegum/README.md @@ -0,0 +1,14 @@ +# Bubblegum + +This SDK uses MPL's `Solita` to generate typescript SDK for `anchor` smart-contract. + +Solita is particularly helpful: +- Enums: (i.e. TokenProgramVersion) +- Complex types: (ie MetadataArgs support) +- Using typed system to identify issues with smart contract args + +### Install + +1. `yarn` +2. `node solita.js` +3. `import { ... } from '../sdk/bubblegum'` From da377e0d546c3e247b8a351b704d404c1fcb3dec Mon Sep 17 00:00:00 2001 From: Noah Gundotra Date: Mon, 6 Jun 2022 11:42:04 -0700 Subject: [PATCH 4/8] add solita for gumball-machine --- .../gumball-machine/idl/gumball_machine.json | 583 ++++++++++++++++++ contracts/sdk/gumball-machine/package.json | 10 + contracts/sdk/gumball-machine/solita.js | 74 +++ .../gumball-machine/src/generated/index.ts | 19 + .../generated/instructions/addConfigLines.ts | 94 +++ .../src/generated/instructions/destroy.ts | 75 +++ .../generated/instructions/dispenseNftSol.ts | 174 ++++++ .../instructions/dispenseNftToken.ts | 183 ++++++ .../src/generated/instructions/index.ts | 7 + .../instructions/initializeGumballMachine.ts | 178 ++++++ .../instructions/updateConfigLines.ts | 96 +++ .../instructions/updateHeaderMetadata.ts | 115 ++++ .../generated/types/GumballMachineHeader.ts | 63 ++ .../src/generated/types/index.ts | 1 + 14 files changed, 1672 insertions(+) create mode 100644 contracts/sdk/gumball-machine/idl/gumball_machine.json create mode 100644 contracts/sdk/gumball-machine/package.json create mode 100644 contracts/sdk/gumball-machine/solita.js create mode 100644 contracts/sdk/gumball-machine/src/generated/index.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/instructions/addConfigLines.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/instructions/destroy.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/instructions/dispenseNftSol.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/instructions/dispenseNftToken.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/instructions/index.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/instructions/initializeGumballMachine.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/instructions/updateConfigLines.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/instructions/updateHeaderMetadata.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/types/GumballMachineHeader.ts create mode 100644 contracts/sdk/gumball-machine/src/generated/types/index.ts diff --git a/contracts/sdk/gumball-machine/idl/gumball_machine.json b/contracts/sdk/gumball-machine/idl/gumball_machine.json new file mode 100644 index 00000000000..c101a58ad24 --- /dev/null +++ b/contracts/sdk/gumball-machine/idl/gumball_machine.json @@ -0,0 +1,583 @@ +{ + "version": "0.1.0", + "name": "gumball_machine", + "instructions": [ + { + "name": "initializeGumballMachine", + "accounts": [ + { + "name": "gumballMachine", + "isMut": true, + "isSigner": false + }, + { + "name": "creator", + "isMut": false, + "isSigner": true + }, + { + "name": "mint", + "isMut": false, + "isSigner": false + }, + { + "name": "willyWonka", + "isMut": false, + "isSigner": false + }, + { + "name": "bubblegumAuthority", + "isMut": false, + "isSigner": false + }, + { + "name": "gummyroll", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + }, + { + "name": "bubblegum", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "maxDepth", + "type": "u32" + }, + { + "name": "maxBufferSize", + "type": "u32" + }, + { + "name": "urlBase", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "nameBase", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "symbol", + "type": { + "array": [ + "u8", + 8 + ] + } + }, + { + "name": "sellerFeeBasisPoints", + "type": "u16" + }, + { + "name": "isMutable", + "type": "bool" + }, + { + "name": "retainAuthority", + "type": "bool" + }, + { + "name": "price", + "type": "u64" + }, + { + "name": "goLiveDate", + "type": "i64" + }, + { + "name": "botWallet", + "type": "publicKey" + }, + { + "name": "receiver", + "type": "publicKey" + }, + { + "name": "authority", + "type": "publicKey" + }, + { + "name": "collectionKey", + "type": "publicKey" + }, + { + "name": "extensionLen", + "type": "u64" + }, + { + "name": "maxMintSize", + "type": "u64" + }, + { + "name": "maxItems", + "type": "u64" + } + ] + }, + { + "name": "addConfigLines", + "docs": [ + "Add can only append config lines to the the end of the list" + ], + "accounts": [ + { + "name": "gumballMachine", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "newConfigLinesData", + "type": "bytes" + } + ] + }, + { + "name": "updateConfigLines", + "docs": [ + "Update only allows the authority to modify previously appended lines" + ], + "accounts": [ + { + "name": "gumballMachine", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "startingLine", + "type": "u64" + }, + { + "name": "newConfigLinesData", + "type": "bytes" + } + ] + }, + { + "name": "updateHeaderMetadata", + "accounts": [ + { + "name": "gumballMachine", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "urlBase", + "type": { + "option": { + "array": [ + "u8", + 64 + ] + } + } + }, + { + "name": "nameBase", + "type": { + "option": { + "array": [ + "u8", + 32 + ] + } + } + }, + { + "name": "symbol", + "type": { + "option": { + "array": [ + "u8", + 8 + ] + } + } + }, + { + "name": "sellerFeeBasisPoints", + "type": { + "option": "u16" + } + }, + { + "name": "isMutable", + "type": { + "option": "bool" + } + }, + { + "name": "retainAuthority", + "type": { + "option": "bool" + } + }, + { + "name": "price", + "type": { + "option": "u64" + } + }, + { + "name": "goLiveDate", + "type": { + "option": "i64" + } + }, + { + "name": "botWallet", + "type": { + "option": "publicKey" + } + }, + { + "name": "authority", + "type": { + "option": "publicKey" + } + }, + { + "name": "maxMintSize", + "type": { + "option": "u64" + } + } + ] + }, + { + "name": "dispenseNftSol", + "docs": [ + "Request to purchase a random NFT from GumballMachine for a specific project.", + "@notice: the project must have specified the native mint (Wrapped SOL) for \"mint\"", + "in its GumballMachineHeader for this method to succeed. If mint is anything", + "else dispense_nft_token should be used." + ], + "accounts": [ + { + "name": "gumballMachine", + "isMut": true, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "receiver", + "isMut": true, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "willyWonka", + "isMut": false, + "isSigner": false + }, + { + "name": "recentBlockhashes", + "isMut": false, + "isSigner": false + }, + { + "name": "instructionSysvarAccount", + "isMut": false, + "isSigner": false + }, + { + "name": "bubblegumAuthority", + "isMut": false, + "isSigner": false, + "docs": [ + "This key must sign for all write operations to the NFT Metadata stored in the Merkle slab" + ] + }, + { + "name": "nonce", + "isMut": true, + "isSigner": false + }, + { + "name": "gummyroll", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + }, + { + "name": "bubblegum", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "numItems", + "type": "u64" + } + ] + }, + { + "name": "dispenseNftToken", + "docs": [ + "Request to purchase a random NFT from GumballMachine for a specific project.", + "@notice: the project's mint may be any valid Mint account EXCEPT for Wrapped SOL", + "if the mint is Wrapped SOL then dispense_token_sol should be used, as the", + "project is seeking native SOL as payment." + ], + "accounts": [ + { + "name": "gumballMachine", + "isMut": true, + "isSigner": false + }, + { + "name": "payer", + "isMut": false, + "isSigner": true + }, + { + "name": "payerTokens", + "isMut": true, + "isSigner": false + }, + { + "name": "receiver", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "willyWonka", + "isMut": false, + "isSigner": false + }, + { + "name": "recentBlockhashes", + "isMut": false, + "isSigner": false + }, + { + "name": "instructionSysvarAccount", + "isMut": false, + "isSigner": false + }, + { + "name": "bubblegumAuthority", + "isMut": false, + "isSigner": false, + "docs": [ + "This key must sign for all write operations to the NFT Metadata stored in the Merkle slab" + ] + }, + { + "name": "nonce", + "isMut": true, + "isSigner": false + }, + { + "name": "gummyroll", + "isMut": false, + "isSigner": false + }, + { + "name": "merkleSlab", + "isMut": true, + "isSigner": false + }, + { + "name": "bubblegum", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "numItems", + "type": "u64" + } + ] + }, + { + "name": "destroy", + "docs": [ + "Reclaim gumball_machine lamports to authority" + ], + "accounts": [ + { + "name": "gumballMachine", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": true, + "isSigner": true + } + ], + "args": [] + } + ], + "types": [ + { + "name": "GumballMachineHeader", + "type": { + "kind": "struct", + "fields": [ + { + "name": "urlBase", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "nameBase", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "symbol", + "type": { + "array": [ + "u8", + 8 + ] + } + }, + { + "name": "sellerFeeBasisPoints", + "type": "u16" + }, + { + "name": "isMutable", + "type": "u8" + }, + { + "name": "retainAuthority", + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 4 + ] + } + }, + { + "name": "price", + "type": "u64" + }, + { + "name": "goLiveDate", + "type": "i64" + }, + { + "name": "mint", + "type": "publicKey" + }, + { + "name": "botWallet", + "type": "publicKey" + }, + { + "name": "receiver", + "type": "publicKey" + }, + { + "name": "authority", + "type": "publicKey" + }, + { + "name": "collectionKey", + "type": "publicKey" + }, + { + "name": "creatorAddress", + "type": "publicKey" + }, + { + "name": "extensionLen", + "type": "u64" + }, + { + "name": "maxMintSize", + "type": "u64" + }, + { + "name": "remaining", + "type": "u64" + }, + { + "name": "maxItems", + "type": "u64" + }, + { + "name": "totalItemsAdded", + "type": "u64" + } + ] + } + } + ], + "metadata": { + "address": "BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt" + } +} \ No newline at end of file diff --git a/contracts/sdk/gumball-machine/package.json b/contracts/sdk/gumball-machine/package.json new file mode 100644 index 00000000000..9b91acef2cb --- /dev/null +++ b/contracts/sdk/gumball-machine/package.json @@ -0,0 +1,10 @@ +{ + "name": "gumball-machine", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "@metaplex-foundation/rustbin": "^0.3.1", + "@metaplex-foundation/solita": "^0.8.2" + } +} diff --git a/contracts/sdk/gumball-machine/solita.js b/contracts/sdk/gumball-machine/solita.js new file mode 100644 index 00000000000..4ca0c3315d5 --- /dev/null +++ b/contracts/sdk/gumball-machine/solita.js @@ -0,0 +1,74 @@ +const path = require('path'); +const { + rustbinMatch, + confirmAutoMessageConsole, +} = require('@metaplex-foundation/rustbin') +const { spawn } = require('child_process'); +const { Solita } = require('@metaplex-foundation/solita'); +const { writeFile } = require('fs/promises'); +const { fstat, existsSync } = require('fs'); + +const PROGRAM_NAME = 'gumball-machine'; +const PROGRAM_ID = 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt'; + +const programDir = path.join(__dirname, '..', '..', 'programs', 'gumball-machine'); +const cargoToml = path.join(programDir, 'Cargo.toml') +const generatedIdlDir = path.join(__dirname, 'idl'); +const generatedSDKDir = path.join(__dirname, 'src', 'generated'); +const rootDir = path.join(__dirname, '.crates') +const rustbinConfig = { + rootDir, + binaryName: 'anchor', + binaryCrateName: 'anchor-cli', + libName: 'anchor-lang', + dryRun: false, + cargoToml, +} + +async function main() { + const anchorExecutable = ("~/Documents/core/candyland/deps/anchor/target/debug/anchor").replace("~", process.env.HOME); + if (!existsSync(anchorExecutable)) { + console.log(`Could not find: ${anchorExecutable}`); + throw new Error("Please `cd candyland/deps/anchor/anchor-cli` && cargo build`") + } + const anchor = spawn(anchorExecutable, ['build', '--idl', generatedIdlDir], { cwd: programDir }) + .on('error', (err) => { + console.error(err); + // @ts-ignore this err does have a code + if (err.code === 'ENOENT') { + console.error( + 'Ensure that `anchor` is installed and in your path, see:\n https://project-serum.github.io/anchor/getting-started/installation.html#install-anchor\n', + ); + } + process.exit(1); + }) + .on('exit', () => { + console.log('IDL written to: %s', path.join(generatedIdlDir, `${PROGRAM_NAME.replace("-", '_')}.json`)); + generateTypeScriptSDK(); + }); + + anchor.stdout.on('data', (buf) => console.log(buf.toString('utf8'))); + anchor.stderr.on('data', (buf) => console.error(buf.toString('utf8'))); +} + +async function generateTypeScriptSDK() { + console.error('Generating TypeScript SDK to %s', generatedSDKDir); + const generatedIdlPath = path.join(generatedIdlDir, `${PROGRAM_NAME.replace("-", "_")}.json`); + + const idl = require(generatedIdlPath); + if (idl.metadata?.address == null) { + idl.metadata = { ...idl.metadata, address: PROGRAM_ID }; + await writeFile(generatedIdlPath, JSON.stringify(idl, null, 2)); + } + const gen = new Solita(idl, { formatCode: true }); + await gen.renderAndWriteTo(generatedSDKDir); + + console.error('Success!'); + + process.exit(0); +} + +main().catch((err) => { + console.error(err) + process.exit(1) +}) diff --git a/contracts/sdk/gumball-machine/src/generated/index.ts b/contracts/sdk/gumball-machine/src/generated/index.ts new file mode 100644 index 00000000000..41c9d408634 --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/index.ts @@ -0,0 +1,19 @@ +import { PublicKey } from '@solana/web3.js' +export * from './instructions' +export * from './types' + +/** + * Program address + * + * @category constants + * @category generated + */ +export const PROGRAM_ADDRESS = 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt' + +/** + * Program public key + * + * @category constants + * @category generated + */ +export const PROGRAM_ID = new PublicKey(PROGRAM_ADDRESS) diff --git a/contracts/sdk/gumball-machine/src/generated/instructions/addConfigLines.ts b/contracts/sdk/gumball-machine/src/generated/instructions/addConfigLines.ts new file mode 100644 index 00000000000..eedc4afe9ed --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/instructions/addConfigLines.ts @@ -0,0 +1,94 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * @category Instructions + * @category AddConfigLines + * @category generated + */ +export type AddConfigLinesInstructionArgs = { + newConfigLinesData: Uint8Array +} +/** + * @category Instructions + * @category AddConfigLines + * @category generated + */ +export const addConfigLinesStruct = new beet.FixableBeetArgsStruct< + AddConfigLinesInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['newConfigLinesData', beet.bytes], + ], + 'AddConfigLinesInstructionArgs' +) +/** + * Accounts required by the _addConfigLines_ instruction + * + * @property [_writable_] gumballMachine + * @property [**signer**] authority + * @category Instructions + * @category AddConfigLines + * @category generated + */ +export type AddConfigLinesInstructionAccounts = { + gumballMachine: web3.PublicKey + authority: web3.PublicKey +} + +export const addConfigLinesInstructionDiscriminator = [ + 223, 50, 224, 227, 151, 8, 115, 106, +] + +/** + * Creates a _AddConfigLines_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category AddConfigLines + * @category generated + */ +export function createAddConfigLinesInstruction( + accounts: AddConfigLinesInstructionAccounts, + args: AddConfigLinesInstructionArgs +) { + const { gumballMachine, authority } = accounts + + const [data] = addConfigLinesStruct.serialize({ + instructionDiscriminator: addConfigLinesInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: gumballMachine, + isWritable: true, + isSigner: false, + }, + { + pubkey: authority, + isWritable: false, + isSigner: true, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/gumball-machine/src/generated/instructions/destroy.ts b/contracts/sdk/gumball-machine/src/generated/instructions/destroy.ts new file mode 100644 index 00000000000..54c5d33811f --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/instructions/destroy.ts @@ -0,0 +1,75 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * @category Instructions + * @category Destroy + * @category generated + */ +export const destroyStruct = new beet.BeetArgsStruct<{ + instructionDiscriminator: number[] /* size: 8 */ +}>( + [['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)]], + 'DestroyInstructionArgs' +) +/** + * Accounts required by the _destroy_ instruction + * + * @property [_writable_] gumballMachine + * @property [_writable_, **signer**] authority + * @category Instructions + * @category Destroy + * @category generated + */ +export type DestroyInstructionAccounts = { + gumballMachine: web3.PublicKey + authority: web3.PublicKey +} + +export const destroyInstructionDiscriminator = [ + 157, 40, 96, 3, 135, 203, 143, 74, +] + +/** + * Creates a _Destroy_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @category Instructions + * @category Destroy + * @category generated + */ +export function createDestroyInstruction(accounts: DestroyInstructionAccounts) { + const { gumballMachine, authority } = accounts + + const [data] = destroyStruct.serialize({ + instructionDiscriminator: destroyInstructionDiscriminator, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: gumballMachine, + isWritable: true, + isSigner: false, + }, + { + pubkey: authority, + isWritable: true, + isSigner: true, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/gumball-machine/src/generated/instructions/dispenseNftSol.ts b/contracts/sdk/gumball-machine/src/generated/instructions/dispenseNftSol.ts new file mode 100644 index 00000000000..d133fc0897e --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/instructions/dispenseNftSol.ts @@ -0,0 +1,174 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * @category Instructions + * @category DispenseNftSol + * @category generated + */ +export type DispenseNftSolInstructionArgs = { + numItems: beet.bignum +} +/** + * @category Instructions + * @category DispenseNftSol + * @category generated + */ +export const dispenseNftSolStruct = new beet.BeetArgsStruct< + DispenseNftSolInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['numItems', beet.u64], + ], + 'DispenseNftSolInstructionArgs' +) +/** + * Accounts required by the _dispenseNftSol_ instruction + * + * @property [_writable_] gumballMachine + * @property [_writable_, **signer**] payer + * @property [_writable_] receiver + * @property [] willyWonka + * @property [] recentBlockhashes + * @property [] instructionSysvarAccount + * @property [] bubblegumAuthority + * @property [_writable_] nonce + * @property [] gummyroll + * @property [_writable_] merkleSlab + * @property [] bubblegum + * @category Instructions + * @category DispenseNftSol + * @category generated + */ +export type DispenseNftSolInstructionAccounts = { + gumballMachine: web3.PublicKey + payer: web3.PublicKey + receiver: web3.PublicKey + willyWonka: web3.PublicKey + recentBlockhashes: web3.PublicKey + instructionSysvarAccount: web3.PublicKey + bubblegumAuthority: web3.PublicKey + nonce: web3.PublicKey + gummyroll: web3.PublicKey + merkleSlab: web3.PublicKey + bubblegum: web3.PublicKey +} + +export const dispenseNftSolInstructionDiscriminator = [ + 156, 55, 115, 151, 225, 40, 172, 61, +] + +/** + * Creates a _DispenseNftSol_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category DispenseNftSol + * @category generated + */ +export function createDispenseNftSolInstruction( + accounts: DispenseNftSolInstructionAccounts, + args: DispenseNftSolInstructionArgs +) { + const { + gumballMachine, + payer, + receiver, + willyWonka, + recentBlockhashes, + instructionSysvarAccount, + bubblegumAuthority, + nonce, + gummyroll, + merkleSlab, + bubblegum, + } = accounts + + const [data] = dispenseNftSolStruct.serialize({ + instructionDiscriminator: dispenseNftSolInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: gumballMachine, + isWritable: true, + isSigner: false, + }, + { + pubkey: payer, + isWritable: true, + isSigner: true, + }, + { + pubkey: receiver, + isWritable: true, + isSigner: false, + }, + { + pubkey: web3.SystemProgram.programId, + isWritable: false, + isSigner: false, + }, + { + pubkey: willyWonka, + isWritable: false, + isSigner: false, + }, + { + pubkey: recentBlockhashes, + isWritable: false, + isSigner: false, + }, + { + pubkey: instructionSysvarAccount, + isWritable: false, + isSigner: false, + }, + { + pubkey: bubblegumAuthority, + isWritable: false, + isSigner: false, + }, + { + pubkey: nonce, + isWritable: true, + isSigner: false, + }, + { + pubkey: gummyroll, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + { + pubkey: bubblegum, + isWritable: false, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/gumball-machine/src/generated/instructions/dispenseNftToken.ts b/contracts/sdk/gumball-machine/src/generated/instructions/dispenseNftToken.ts new file mode 100644 index 00000000000..fd13e3786e4 --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/instructions/dispenseNftToken.ts @@ -0,0 +1,183 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as splToken from '@solana/spl-token' +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * @category Instructions + * @category DispenseNftToken + * @category generated + */ +export type DispenseNftTokenInstructionArgs = { + numItems: beet.bignum +} +/** + * @category Instructions + * @category DispenseNftToken + * @category generated + */ +export const dispenseNftTokenStruct = new beet.BeetArgsStruct< + DispenseNftTokenInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['numItems', beet.u64], + ], + 'DispenseNftTokenInstructionArgs' +) +/** + * Accounts required by the _dispenseNftToken_ instruction + * + * @property [_writable_] gumballMachine + * @property [**signer**] payer + * @property [_writable_] payerTokens + * @property [_writable_] receiver + * @property [] willyWonka + * @property [] recentBlockhashes + * @property [] instructionSysvarAccount + * @property [] bubblegumAuthority + * @property [_writable_] nonce + * @property [] gummyroll + * @property [_writable_] merkleSlab + * @property [] bubblegum + * @category Instructions + * @category DispenseNftToken + * @category generated + */ +export type DispenseNftTokenInstructionAccounts = { + gumballMachine: web3.PublicKey + payer: web3.PublicKey + payerTokens: web3.PublicKey + receiver: web3.PublicKey + willyWonka: web3.PublicKey + recentBlockhashes: web3.PublicKey + instructionSysvarAccount: web3.PublicKey + bubblegumAuthority: web3.PublicKey + nonce: web3.PublicKey + gummyroll: web3.PublicKey + merkleSlab: web3.PublicKey + bubblegum: web3.PublicKey +} + +export const dispenseNftTokenInstructionDiscriminator = [ + 55, 215, 72, 66, 100, 249, 57, 225, +] + +/** + * Creates a _DispenseNftToken_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category DispenseNftToken + * @category generated + */ +export function createDispenseNftTokenInstruction( + accounts: DispenseNftTokenInstructionAccounts, + args: DispenseNftTokenInstructionArgs +) { + const { + gumballMachine, + payer, + payerTokens, + receiver, + willyWonka, + recentBlockhashes, + instructionSysvarAccount, + bubblegumAuthority, + nonce, + gummyroll, + merkleSlab, + bubblegum, + } = accounts + + const [data] = dispenseNftTokenStruct.serialize({ + instructionDiscriminator: dispenseNftTokenInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: gumballMachine, + isWritable: true, + isSigner: false, + }, + { + pubkey: payer, + isWritable: false, + isSigner: true, + }, + { + pubkey: payerTokens, + isWritable: true, + isSigner: false, + }, + { + pubkey: receiver, + isWritable: true, + isSigner: false, + }, + { + pubkey: splToken.TOKEN_PROGRAM_ID, + isWritable: false, + isSigner: false, + }, + { + pubkey: willyWonka, + isWritable: false, + isSigner: false, + }, + { + pubkey: recentBlockhashes, + isWritable: false, + isSigner: false, + }, + { + pubkey: instructionSysvarAccount, + isWritable: false, + isSigner: false, + }, + { + pubkey: bubblegumAuthority, + isWritable: false, + isSigner: false, + }, + { + pubkey: nonce, + isWritable: true, + isSigner: false, + }, + { + pubkey: gummyroll, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + { + pubkey: bubblegum, + isWritable: false, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/gumball-machine/src/generated/instructions/index.ts b/contracts/sdk/gumball-machine/src/generated/instructions/index.ts new file mode 100644 index 00000000000..9a5c377418a --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/instructions/index.ts @@ -0,0 +1,7 @@ +export * from './addConfigLines' +export * from './destroy' +export * from './dispenseNftSol' +export * from './dispenseNftToken' +export * from './initializeGumballMachine' +export * from './updateConfigLines' +export * from './updateHeaderMetadata' diff --git a/contracts/sdk/gumball-machine/src/generated/instructions/initializeGumballMachine.ts b/contracts/sdk/gumball-machine/src/generated/instructions/initializeGumballMachine.ts new file mode 100644 index 00000000000..62935efd427 --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/instructions/initializeGumballMachine.ts @@ -0,0 +1,178 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' +import * as beetSolana from '@metaplex-foundation/beet-solana' + +/** + * @category Instructions + * @category InitializeGumballMachine + * @category generated + */ +export type InitializeGumballMachineInstructionArgs = { + maxDepth: number + maxBufferSize: number + urlBase: number[] /* size: 64 */ + nameBase: number[] /* size: 32 */ + symbol: number[] /* size: 8 */ + sellerFeeBasisPoints: number + isMutable: boolean + retainAuthority: boolean + price: beet.bignum + goLiveDate: beet.bignum + botWallet: web3.PublicKey + receiver: web3.PublicKey + authority: web3.PublicKey + collectionKey: web3.PublicKey + extensionLen: beet.bignum + maxMintSize: beet.bignum + maxItems: beet.bignum +} +/** + * @category Instructions + * @category InitializeGumballMachine + * @category generated + */ +export const initializeGumballMachineStruct = new beet.BeetArgsStruct< + InitializeGumballMachineInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['maxDepth', beet.u32], + ['maxBufferSize', beet.u32], + ['urlBase', beet.uniformFixedSizeArray(beet.u8, 64)], + ['nameBase', beet.uniformFixedSizeArray(beet.u8, 32)], + ['symbol', beet.uniformFixedSizeArray(beet.u8, 8)], + ['sellerFeeBasisPoints', beet.u16], + ['isMutable', beet.bool], + ['retainAuthority', beet.bool], + ['price', beet.u64], + ['goLiveDate', beet.i64], + ['botWallet', beetSolana.publicKey], + ['receiver', beetSolana.publicKey], + ['authority', beetSolana.publicKey], + ['collectionKey', beetSolana.publicKey], + ['extensionLen', beet.u64], + ['maxMintSize', beet.u64], + ['maxItems', beet.u64], + ], + 'InitializeGumballMachineInstructionArgs' +) +/** + * Accounts required by the _initializeGumballMachine_ instruction + * + * @property [_writable_] gumballMachine + * @property [**signer**] creator + * @property [] mint + * @property [] willyWonka + * @property [] bubblegumAuthority + * @property [] gummyroll + * @property [_writable_] merkleSlab + * @property [] bubblegum + * @category Instructions + * @category InitializeGumballMachine + * @category generated + */ +export type InitializeGumballMachineInstructionAccounts = { + gumballMachine: web3.PublicKey + creator: web3.PublicKey + mint: web3.PublicKey + willyWonka: web3.PublicKey + bubblegumAuthority: web3.PublicKey + gummyroll: web3.PublicKey + merkleSlab: web3.PublicKey + bubblegum: web3.PublicKey +} + +export const initializeGumballMachineInstructionDiscriminator = [ + 206, 247, 43, 231, 98, 153, 124, 110, +] + +/** + * Creates a _InitializeGumballMachine_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category InitializeGumballMachine + * @category generated + */ +export function createInitializeGumballMachineInstruction( + accounts: InitializeGumballMachineInstructionAccounts, + args: InitializeGumballMachineInstructionArgs +) { + const { + gumballMachine, + creator, + mint, + willyWonka, + bubblegumAuthority, + gummyroll, + merkleSlab, + bubblegum, + } = accounts + + const [data] = initializeGumballMachineStruct.serialize({ + instructionDiscriminator: initializeGumballMachineInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: gumballMachine, + isWritable: true, + isSigner: false, + }, + { + pubkey: creator, + isWritable: false, + isSigner: true, + }, + { + pubkey: mint, + isWritable: false, + isSigner: false, + }, + { + pubkey: willyWonka, + isWritable: false, + isSigner: false, + }, + { + pubkey: bubblegumAuthority, + isWritable: false, + isSigner: false, + }, + { + pubkey: gummyroll, + isWritable: false, + isSigner: false, + }, + { + pubkey: merkleSlab, + isWritable: true, + isSigner: false, + }, + { + pubkey: bubblegum, + isWritable: false, + isSigner: false, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/gumball-machine/src/generated/instructions/updateConfigLines.ts b/contracts/sdk/gumball-machine/src/generated/instructions/updateConfigLines.ts new file mode 100644 index 00000000000..71442e32ad9 --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/instructions/updateConfigLines.ts @@ -0,0 +1,96 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' + +/** + * @category Instructions + * @category UpdateConfigLines + * @category generated + */ +export type UpdateConfigLinesInstructionArgs = { + startingLine: beet.bignum + newConfigLinesData: Uint8Array +} +/** + * @category Instructions + * @category UpdateConfigLines + * @category generated + */ +export const updateConfigLinesStruct = new beet.FixableBeetArgsStruct< + UpdateConfigLinesInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['startingLine', beet.u64], + ['newConfigLinesData', beet.bytes], + ], + 'UpdateConfigLinesInstructionArgs' +) +/** + * Accounts required by the _updateConfigLines_ instruction + * + * @property [_writable_] gumballMachine + * @property [**signer**] authority + * @category Instructions + * @category UpdateConfigLines + * @category generated + */ +export type UpdateConfigLinesInstructionAccounts = { + gumballMachine: web3.PublicKey + authority: web3.PublicKey +} + +export const updateConfigLinesInstructionDiscriminator = [ + 20, 200, 2, 139, 44, 67, 109, 26, +] + +/** + * Creates a _UpdateConfigLines_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category UpdateConfigLines + * @category generated + */ +export function createUpdateConfigLinesInstruction( + accounts: UpdateConfigLinesInstructionAccounts, + args: UpdateConfigLinesInstructionArgs +) { + const { gumballMachine, authority } = accounts + + const [data] = updateConfigLinesStruct.serialize({ + instructionDiscriminator: updateConfigLinesInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: gumballMachine, + isWritable: true, + isSigner: false, + }, + { + pubkey: authority, + isWritable: false, + isSigner: true, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/gumball-machine/src/generated/instructions/updateHeaderMetadata.ts b/contracts/sdk/gumball-machine/src/generated/instructions/updateHeaderMetadata.ts new file mode 100644 index 00000000000..d95f9f66d68 --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/instructions/updateHeaderMetadata.ts @@ -0,0 +1,115 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' +import * as beetSolana from '@metaplex-foundation/beet-solana' + +/** + * @category Instructions + * @category UpdateHeaderMetadata + * @category generated + */ +export type UpdateHeaderMetadataInstructionArgs = { + urlBase: beet.COption + nameBase: beet.COption + symbol: beet.COption + sellerFeeBasisPoints: beet.COption + isMutable: beet.COption + retainAuthority: beet.COption + price: beet.COption + goLiveDate: beet.COption + botWallet: beet.COption + authority: beet.COption + maxMintSize: beet.COption +} +/** + * @category Instructions + * @category UpdateHeaderMetadata + * @category generated + */ +export const updateHeaderMetadataStruct = new beet.FixableBeetArgsStruct< + UpdateHeaderMetadataInstructionArgs & { + instructionDiscriminator: number[] /* size: 8 */ + } +>( + [ + ['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)], + ['urlBase', beet.coption(beet.uniformFixedSizeArray(beet.u8, 64))], + ['nameBase', beet.coption(beet.uniformFixedSizeArray(beet.u8, 32))], + ['symbol', beet.coption(beet.uniformFixedSizeArray(beet.u8, 8))], + ['sellerFeeBasisPoints', beet.coption(beet.u16)], + ['isMutable', beet.coption(beet.bool)], + ['retainAuthority', beet.coption(beet.bool)], + ['price', beet.coption(beet.u64)], + ['goLiveDate', beet.coption(beet.i64)], + ['botWallet', beet.coption(beetSolana.publicKey)], + ['authority', beet.coption(beetSolana.publicKey)], + ['maxMintSize', beet.coption(beet.u64)], + ], + 'UpdateHeaderMetadataInstructionArgs' +) +/** + * Accounts required by the _updateHeaderMetadata_ instruction + * + * @property [_writable_] gumballMachine + * @property [**signer**] authority + * @category Instructions + * @category UpdateHeaderMetadata + * @category generated + */ +export type UpdateHeaderMetadataInstructionAccounts = { + gumballMachine: web3.PublicKey + authority: web3.PublicKey +} + +export const updateHeaderMetadataInstructionDiscriminator = [ + 103, 76, 66, 120, 245, 72, 217, 123, +] + +/** + * Creates a _UpdateHeaderMetadata_ instruction. + * + * @param accounts that will be accessed while the instruction is processed + * @param args to provide as instruction data to the program + * + * @category Instructions + * @category UpdateHeaderMetadata + * @category generated + */ +export function createUpdateHeaderMetadataInstruction( + accounts: UpdateHeaderMetadataInstructionAccounts, + args: UpdateHeaderMetadataInstructionArgs +) { + const { gumballMachine, authority } = accounts + + const [data] = updateHeaderMetadataStruct.serialize({ + instructionDiscriminator: updateHeaderMetadataInstructionDiscriminator, + ...args, + }) + const keys: web3.AccountMeta[] = [ + { + pubkey: gumballMachine, + isWritable: true, + isSigner: false, + }, + { + pubkey: authority, + isWritable: false, + isSigner: true, + }, + ] + + const ix = new web3.TransactionInstruction({ + programId: new web3.PublicKey( + 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt' + ), + keys, + data, + }) + return ix +} diff --git a/contracts/sdk/gumball-machine/src/generated/types/GumballMachineHeader.ts b/contracts/sdk/gumball-machine/src/generated/types/GumballMachineHeader.ts new file mode 100644 index 00000000000..032ace3a304 --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/types/GumballMachineHeader.ts @@ -0,0 +1,63 @@ +/** + * This code was GENERATED using the solita package. + * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. + * + * See: https://github.com/metaplex-foundation/solita + */ + +import * as beet from '@metaplex-foundation/beet' +import * as web3 from '@solana/web3.js' +import * as beetSolana from '@metaplex-foundation/beet-solana' +export type GumballMachineHeader = { + urlBase: number[] /* size: 64 */ + nameBase: number[] /* size: 32 */ + symbol: number[] /* size: 8 */ + sellerFeeBasisPoints: number + isMutable: number + retainAuthority: number + padding: number[] /* size: 4 */ + price: beet.bignum + goLiveDate: beet.bignum + mint: web3.PublicKey + botWallet: web3.PublicKey + receiver: web3.PublicKey + authority: web3.PublicKey + collectionKey: web3.PublicKey + creatorAddress: web3.PublicKey + extensionLen: beet.bignum + maxMintSize: beet.bignum + remaining: beet.bignum + maxItems: beet.bignum + totalItemsAdded: beet.bignum +} + +/** + * @category userTypes + * @category generated + */ +export const gumballMachineHeaderBeet = + new beet.BeetArgsStruct( + [ + ['urlBase', beet.uniformFixedSizeArray(beet.u8, 64)], + ['nameBase', beet.uniformFixedSizeArray(beet.u8, 32)], + ['symbol', beet.uniformFixedSizeArray(beet.u8, 8)], + ['sellerFeeBasisPoints', beet.u16], + ['isMutable', beet.u8], + ['retainAuthority', beet.u8], + ['padding', beet.uniformFixedSizeArray(beet.u8, 4)], + ['price', beet.u64], + ['goLiveDate', beet.i64], + ['mint', beetSolana.publicKey], + ['botWallet', beetSolana.publicKey], + ['receiver', beetSolana.publicKey], + ['authority', beetSolana.publicKey], + ['collectionKey', beetSolana.publicKey], + ['creatorAddress', beetSolana.publicKey], + ['extensionLen', beet.u64], + ['maxMintSize', beet.u64], + ['remaining', beet.u64], + ['maxItems', beet.u64], + ['totalItemsAdded', beet.u64], + ], + 'GumballMachineHeader' + ) diff --git a/contracts/sdk/gumball-machine/src/generated/types/index.ts b/contracts/sdk/gumball-machine/src/generated/types/index.ts new file mode 100644 index 00000000000..9c34097005a --- /dev/null +++ b/contracts/sdk/gumball-machine/src/generated/types/index.ts @@ -0,0 +1 @@ +export * from './GumballMachineHeader' From 86e905919d9b3d8592bfd80c0205046afc5a2fc5 Mon Sep 17 00:00:00 2001 From: Noah Gundotra Date: Mon, 6 Jun 2022 11:46:20 -0700 Subject: [PATCH 5/8] make solita scripts more robust --- contracts/sdk/bubblegum/solita.js | 10 +--------- contracts/sdk/gumball-machine/solita.js | 13 +++---------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/contracts/sdk/bubblegum/solita.js b/contracts/sdk/bubblegum/solita.js index 65b394f9b17..09f43fb6207 100644 --- a/contracts/sdk/bubblegum/solita.js +++ b/contracts/sdk/bubblegum/solita.js @@ -16,17 +16,9 @@ const cargoToml = path.join(programDir, 'Cargo.toml') const generatedIdlDir = path.join(__dirname, 'idl'); const generatedSDKDir = path.join(__dirname, 'src', 'generated'); const rootDir = path.join(__dirname, '.crates') -const rustbinConfig = { - rootDir, - binaryName: 'anchor', - binaryCrateName: 'anchor-cli', - libName: 'anchor-lang', - dryRun: false, - cargoToml, -} async function main() { - const anchorExecutable = ("~/Documents/core/candyland/deps/anchor/target/debug/anchor").replace("~", process.env.HOME); + const anchorExecutable = realpathSync("../../../deps/anchor/target/debug/anchor"); if (!existsSync(anchorExecutable)) { console.log(`Could not find: ${anchorExecutable}`); throw new Error("Please `cd candyland/deps/anchor/anchor-cli` && cargo build`") diff --git a/contracts/sdk/gumball-machine/solita.js b/contracts/sdk/gumball-machine/solita.js index 4ca0c3315d5..4131eaec3c0 100644 --- a/contracts/sdk/gumball-machine/solita.js +++ b/contracts/sdk/gumball-machine/solita.js @@ -6,7 +6,7 @@ const { const { spawn } = require('child_process'); const { Solita } = require('@metaplex-foundation/solita'); const { writeFile } = require('fs/promises'); -const { fstat, existsSync } = require('fs'); +const { fstat, existsSync, realpath, realpathSync } = require('fs'); const PROGRAM_NAME = 'gumball-machine'; const PROGRAM_ID = 'BRKyVDRGT7SPBtMhjHN4PVSPVYoc3Wa3QTyuRVM4iZkt'; @@ -16,17 +16,10 @@ const cargoToml = path.join(programDir, 'Cargo.toml') const generatedIdlDir = path.join(__dirname, 'idl'); const generatedSDKDir = path.join(__dirname, 'src', 'generated'); const rootDir = path.join(__dirname, '.crates') -const rustbinConfig = { - rootDir, - binaryName: 'anchor', - binaryCrateName: 'anchor-cli', - libName: 'anchor-lang', - dryRun: false, - cargoToml, -} async function main() { - const anchorExecutable = ("~/Documents/core/candyland/deps/anchor/target/debug/anchor").replace("~", process.env.HOME); + const anchorExecutable = realpathSync("../../../deps/anchor/target/debug/anchor"); + // const anchorExecutable = ("~/Documents/core/candyland/deps/anchor/target/debug/anchor").replace("~", process.env.HOME); if (!existsSync(anchorExecutable)) { console.log(`Could not find: ${anchorExecutable}`); throw new Error("Please `cd candyland/deps/anchor/anchor-cli` && cargo build`") From 8f1b2678dd225e4591ef7ec8906ffab9e147f8ff Mon Sep 17 00:00:00 2001 From: Sam Orend Date: Tue, 7 Jun 2022 00:02:50 -0400 Subject: [PATCH 6/8] working with solita sdk --- contracts/package.json | 1 + .../sdk/gumball-machine/accounts/index.ts | 45 ++-- .../sdk/gumball-machine/instructions/index.ts | 187 ++++++--------- contracts/sdk/utils/index.ts | 17 ++ contracts/tests/gumball-machine-test.ts | 220 ++++++++++++------ contracts/yarn.lock | 100 +------- 6 files changed, 274 insertions(+), 296 deletions(-) diff --git a/contracts/package.json b/contracts/package.json index a00dde9eaf4..12ab22e21e7 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,6 +1,7 @@ { "dependencies": { "@metaplex-foundation/amman": "^0.0.12", + "@metaplex-foundation/beet": "^0.2.0", "@metaplex-foundation/mpl-core": "^0.0.4", "@metaplex-foundation/mpl-token-metadata": "^2.1.1", "@project-serum/anchor": "^0.21.0", diff --git a/contracts/sdk/gumball-machine/accounts/index.ts b/contracts/sdk/gumball-machine/accounts/index.ts index db03b446bac..e5efb739f58 100644 --- a/contracts/sdk/gumball-machine/accounts/index.ts +++ b/contracts/sdk/gumball-machine/accounts/index.ts @@ -1,9 +1,6 @@ -import { - PublicKey -} from '@solana/web3.js'; import * as borsh from 'borsh'; -import { BN } from '@project-serum/anchor'; -import { readPublicKey } from '../../utils'; +import { val } from '../../utils'; +import { GumballMachineHeader, gumballMachineHeaderBeet } from '../src/generated/types/GumballMachineHeader'; /** * Manually create a model for GumballMachine accounts to deserialize manually @@ -15,7 +12,7 @@ export type OnChainGumballMachine = { export const GUMBALL_MACHINE_HEADER_SIZE = 360; -type GumballMachineHeader = { +/*type GumballMachineHeader = { urlBase: Buffer, // [u8; 64] nameBase: Buffer, // [u8; 32] symbol: Buffer, // [u8; 8] @@ -36,7 +33,7 @@ type GumballMachineHeader = { remaining: BN, // usize maxItems: BN, // u64 totalItemsAdded: BN, // usize -} +}*/ type ConfigData = { indexArray: Buffer, @@ -45,17 +42,20 @@ type ConfigData = { // Deserialize on-chain gumball machine account to OnChainGumballMachine type export function decodeGumballMachine(buffer: Buffer, accountSize: number): OnChainGumballMachine { - let reader = new borsh.BinaryReader(buffer); + let header: GumballMachineHeader; + let postHeaderOffset: number; + [header, postHeaderOffset] = gumballMachineHeaderBeet.deserialize(buffer); // Deserialize header - let header: GumballMachineHeader = { - urlBase: Buffer.from(reader.readFixedArray(64)), - nameBase: Buffer.from(reader.readFixedArray(32)), - symbol: Buffer.from(reader.readFixedArray(8)), + // TODO(sorend): remove + /*let header: GumballMachineHeader = { + urlBase: Array.from(reader.readFixedArray(64)), + nameBase: Array.from(reader.readFixedArray(32)), + symbol: Array.from(reader.readFixedArray(8)), sellerFeeBasisPoints: reader.readU16(), - isMutable: !!reader.readU8(), - retainAuthority: !!reader.readU8(), - _padding: Buffer.from(reader.readFixedArray(4)), + isMutable: reader.readU8(), + retainAuthority: reader.readU8(), + padding: Array.from(reader.readFixedArray(4)), price: reader.readU64(), goLiveDate: new BN(reader.readFixedArray(8), null, 'le'), mint: readPublicKey(reader), @@ -64,16 +64,19 @@ export function decodeGumballMachine(buffer: Buffer, accountSize: number): OnCha authority: readPublicKey(reader), collectionKey: readPublicKey(reader), creatorAddress: readPublicKey(reader), - extensionLen: new BN(reader.readFixedArray(8), null, 'le'), // Assume 8 byte size of usize...technically could break + extensionLen: new BN(reader.readFixedArray(8), null, 'le'), maxMintSize: reader.readU64(), - remaining: new BN(reader.readFixedArray(8), null, 'le'), // Assume 8 byte size of usize...technically could break + remaining: new BN(reader.readFixedArray(8), null, 'le'), maxItems: reader.readU64(), - totalItemsAdded: new BN(reader.readFixedArray(8), null, 'le'), // Assume 8 byte size of usize...technically could break - }; + totalItemsAdded: new BN(reader.readFixedArray(8), null, 'le'), + };*/ // Deserailize indices and config section - let numIndexArrayBytes = header.maxItems.toNumber() * 4; - let numConfigBytes = header.extensionLen.toNumber() * header.maxItems.toNumber(); + let reader = new borsh.BinaryReader(Buffer.from(buffer)); + // TODO(sorend): nicer would be nice but the Buffer API is not the best + reader.readFixedArray(postHeaderOffset); + let numIndexArrayBytes = 4 * val(header.maxItems).toNumber(); + let numConfigBytes = val(header.extensionLen).toNumber() * val(header.maxItems).toNumber(); let configData: ConfigData = { indexArray: Buffer.from(reader.readFixedArray(numIndexArrayBytes)), configLines: Buffer.from(reader.readFixedArray(numConfigBytes)), diff --git a/contracts/sdk/gumball-machine/instructions/index.ts b/contracts/sdk/gumball-machine/instructions/index.ts index 84f28fb25e7..905d98f59c3 100644 --- a/contracts/sdk/gumball-machine/instructions/index.ts +++ b/contracts/sdk/gumball-machine/instructions/index.ts @@ -17,6 +17,17 @@ import { GumballMachine, InitGumballMachineProps } from '../types'; +import { + InitializeGumballMachineInstructionArgs, + UpdateHeaderMetadataInstructionArgs, + UpdateConfigLinesInstructionArgs, + createInitializeGumballMachineInstruction, + createDispenseNftSolInstruction, + createUpdateHeaderMetadataInstruction, + createDestroyInstruction, + createUpdateConfigLinesInstruction, + createDispenseNftTokenInstruction +} from "../src/generated"; import { getWillyWonkaPDAKey, getBubblegumAuthorityPDAKey @@ -25,7 +36,7 @@ import { /** * Client side function to faciliate the creation of instructions for: initialize_gumball_machine * Handles the creation of merkle roll + gumball machine accounts and the initialization of the gumball machine header - * with props from InitGumballMachineProps -> see ../types/index.ts for details + * with props from InitializeGumballMachineInstructionArgs, -> see ../src/generated/instructions/initializeGumballMachine.ts for details * */ export async function createInitializeGumballMachineIxs( payer: Keypair, @@ -33,9 +44,8 @@ export async function createInitializeGumballMachineIxs( gumballMachineAcctSize: number, merkleRollKeypair: Keypair, merkleRollAccountSize: number, - desiredGumballMachineHeader: InitGumballMachineProps, - maxDepth: number, - maxBufferSize: number, + gumballMachineInitArgs: InitializeGumballMachineInstructionArgs, + mint: PublicKey, gummyrollProgramId: PublicKey, bubblegumProgramId: PublicKey, gumballMachine: Program @@ -65,38 +75,20 @@ export async function createInitializeGumballMachineIxs( const willyWonkaPDAKey = await getWillyWonkaPDAKey(gumballMachineAcctKeypair.publicKey, gumballMachine.programId); const bubblegumAuthorityPDAKey = await getBubblegumAuthorityPDAKey(merkleRollKeypair.publicKey, bubblegumProgramId); - const initGumballMachineInstr = gumballMachine.instruction.initializeGumballMachine( - maxDepth, - maxBufferSize, - desiredGumballMachineHeader.urlBase, - desiredGumballMachineHeader.nameBase, - desiredGumballMachineHeader.symbol, - desiredGumballMachineHeader.sellerFeeBasisPoints, - desiredGumballMachineHeader.isMutable, - desiredGumballMachineHeader.retainAuthority, - desiredGumballMachineHeader.price, - desiredGumballMachineHeader.goLiveDate, - desiredGumballMachineHeader.botWallet, - desiredGumballMachineHeader.receiver, - desiredGumballMachineHeader.authority, - desiredGumballMachineHeader.collectionKey, - desiredGumballMachineHeader.extensionLen, - desiredGumballMachineHeader.maxMintSize, - desiredGumballMachineHeader.maxItems, + const initGumballMachineInstr = createInitializeGumballMachineInstruction( { - accounts: { - gumballMachine: gumballMachineAcctKeypair.publicKey, - creator: payer.publicKey, - mint: desiredGumballMachineHeader.mint, - willyWonka: willyWonkaPDAKey, - bubblegumAuthority: bubblegumAuthorityPDAKey, - gummyroll: gummyrollProgramId, - merkleSlab: merkleRollKeypair.publicKey, - bubblegum: bubblegumProgramId - }, - signers: [payer], - } + gumballMachine: gumballMachineAcctKeypair.publicKey, + creator: payer.publicKey, + mint, + willyWonka: willyWonkaPDAKey, + bubblegumAuthority: bubblegumAuthorityPDAKey, + gummyroll: gummyrollProgramId, + merkleSlab: merkleRollKeypair.publicKey, + bubblegum: bubblegumProgramId + }, + gumballMachineInitArgs ); + // initGumballMachineInstr.keys maybe initGumballMachineInstr.keys[].isSigner = true return [allocGumballMachineAcctInstr, allocMerkleRollAcctInstr, initGumballMachineInstr]; } @@ -107,28 +99,14 @@ export async function createInitializeGumballMachineIxs( export function createUpdateHeaderMetadataIx( authority: Keypair, gumballMachineAcctKey: PublicKey, - newHeader: InitGumballMachineProps, - gumballMachine: Program + updateHeaderArgs: UpdateHeaderMetadataInstructionArgs, ): TransactionInstruction { - const updateHeaderMetadataInstr = gumballMachine.instruction.updateHeaderMetadata( - newHeader.urlBase, - newHeader.nameBase, - newHeader.symbol, - newHeader.sellerFeeBasisPoints, - newHeader.isMutable, - newHeader.retainAuthority, - newHeader.price, - newHeader.goLiveDate, - newHeader.botWallet, - newHeader.authority, - newHeader.maxMintSize, + const updateHeaderMetadataInstr = createUpdateHeaderMetadataInstruction( { - accounts: { - gumballMachine: gumballMachineAcctKey, - authority: authority.publicKey - }, - signers: [authority] - } + gumballMachine: gumballMachineAcctKey, + authority: authority.publicKey + }, + updateHeaderArgs ); return updateHeaderMetadataInstr; } @@ -150,25 +128,24 @@ export async function createDispenseNFTForSolIx( ): Promise { const willyWonkaPDAKey = await getWillyWonkaPDAKey(gumballMachineAcctKeypair.publicKey, gumballMachine.programId); const bubblegumAuthorityPDAKey = await getBubblegumAuthorityPDAKey(merkleRollKeypair.publicKey, bubblegumProgramId); - const dispenseInstr = gumballMachine.instruction.dispenseNftSol( - numNFTs, - { - accounts: { - gumballMachine: gumballMachineAcctKeypair.publicKey, - payer: payer.publicKey, - receiver: receiver, - systemProgram: SystemProgram.programId, - willyWonka: willyWonkaPDAKey, - recentBlockhashes: SYSVAR_SLOT_HASHES_PUBKEY, - instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY, - bubblegumAuthority: bubblegumAuthorityPDAKey, - nonce: noncePDAKey, - gummyroll: gummyrollProgramId, - merkleSlab: merkleRollKeypair.publicKey, - bubblegum: bubblegumProgramId - }, - signers: [payer] - } + const dispenseInstr = createDispenseNftSolInstruction( + { + gumballMachine: gumballMachineAcctKeypair.publicKey, + payer: payer.publicKey, + receiver: receiver, + //systemProgram: SystemProgram.programId, + willyWonka: willyWonkaPDAKey, + recentBlockhashes: SYSVAR_SLOT_HASHES_PUBKEY, + instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY, + bubblegumAuthority: bubblegumAuthorityPDAKey, + nonce: noncePDAKey, + gummyroll: gummyrollProgramId, + merkleSlab: merkleRollKeypair.publicKey, + bubblegum: bubblegumProgramId + }, + { + numItems: numNFTs + } ); return dispenseInstr; } @@ -191,25 +168,23 @@ export async function createDispenseNFTForTokensIx( ): Promise { const willyWonkaPDAKey = await getWillyWonkaPDAKey(gumballMachineAcctKeypair.publicKey, gumballMachine.programId); const bubblegumAuthorityPDAKey = await getBubblegumAuthorityPDAKey(merkleRollKeypair.publicKey, bubblegumProgramId); - const dispenseInstr = gumballMachine.instruction.dispenseNftToken( - numNFTs, + const dispenseInstr = createDispenseNftTokenInstruction( { - accounts: { - gumballMachine: gumballMachineAcctKeypair.publicKey, - payer: payer.publicKey, - payerTokens, - receiver, - tokenProgram: TOKEN_PROGRAM_ID, - willyWonka: willyWonkaPDAKey, - recentBlockhashes: SYSVAR_SLOT_HASHES_PUBKEY, - instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY, - bubblegumAuthority: bubblegumAuthorityPDAKey, - nonce: noncePDAKey, - gummyroll: gummyrollProgramId, - merkleSlab: merkleRollKeypair.publicKey, - bubblegum: bubblegumProgramId - }, - signers: [payer] + gumballMachine: gumballMachineAcctKeypair.publicKey, + payer: payer.publicKey, + payerTokens, + receiver, + willyWonka: willyWonkaPDAKey, + recentBlockhashes: SYSVAR_SLOT_HASHES_PUBKEY, + instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY, + bubblegumAuthority: bubblegumAuthorityPDAKey, + nonce: noncePDAKey, + gummyroll: gummyrollProgramId, + merkleSlab: merkleRollKeypair.publicKey, + bubblegum: bubblegumProgramId + }, + { + numItems: numNFTs } ); return dispenseInstr; @@ -219,7 +194,7 @@ export async function createDispenseNFTForTokensIx( * Client side function to create instruction: add_config_lines. * Enables gumballMachine authority to add config lines -> compressed NFTs that can be minted * */ -export function createAddConfigLinesIx( +/*export function createAddConfigLinesIx( authority: Keypair, gumballMachineAcctKey: PublicKey, configLinesToAdd: Buffer, @@ -236,7 +211,7 @@ export function createAddConfigLinesIx( } ) return addConfigLinesInstr; -} +}*/ /** * Client side function to create instruction: destroy @@ -245,16 +220,12 @@ export function createAddConfigLinesIx( * */ export function createDestroyGumballMachineIx( gumballMachineAcctKeypair: Keypair, - authorityKeypair: Keypair, - gumballMachine: Program + authorityKeypair: Keypair ): TransactionInstruction { - const destroyInstr = gumballMachine.instruction.destroy( + const destroyInstr = createDestroyInstruction( { - accounts: { gumballMachine: gumballMachineAcctKeypair.publicKey, authority: authorityKeypair.publicKey - }, - signers: [authorityKeypair] } ); return destroyInstr; @@ -267,20 +238,14 @@ export function createDestroyGumballMachineIx( export function createUpdateConfigLinesIx( authority: Keypair, gumballMachineAcctKey: PublicKey, - updatedConfigLines: Buffer, - indexOfFirstLineToUpdate: BN, - gumballMachine: Program + args: UpdateConfigLinesInstructionArgs ): TransactionInstruction { - const updateConfigLinesInstr = gumballMachine.instruction.updateConfigLines( - indexOfFirstLineToUpdate, - updatedConfigLines, + const updateConfigLinesInstr = createUpdateConfigLinesInstruction( { - accounts: { - gumballMachine: gumballMachineAcctKey, - authority: authority.publicKey - }, - signers: [authority] - } + gumballMachine: gumballMachineAcctKey, + authority: authority.publicKey + }, + args ); return updateConfigLinesInstr; } \ No newline at end of file diff --git a/contracts/sdk/utils/index.ts b/contracts/sdk/utils/index.ts index 8ff8ff9c164..e27724e8540 100644 --- a/contracts/sdk/utils/index.ts +++ b/contracts/sdk/utils/index.ts @@ -2,7 +2,24 @@ import { PublicKey } from '@solana/web3.js'; import * as borsh from 'borsh'; +import { bignum } from '@metaplex-foundation/beet' +import { BN } from '@project-serum/anchor'; export function readPublicKey(reader: borsh.BinaryReader): PublicKey { return new PublicKey(reader.readFixedArray(32)); +} + +export function val(num: bignum): BN { + if (BN.isBN(num)) { + return num; + } + return new BN(num); +} + +export function strToByteArray(str: string): number[] { + return [...str].reduce((acc, c, ind) => acc.concat([str.charCodeAt(ind)]), []); +} + +export function strToByteUint8Array(str: string): Uint8Array { + return Uint8Array.from([...str].reduce((acc, c, ind) => acc.concat([str.charCodeAt(ind)]), [])); } \ No newline at end of file diff --git a/contracts/tests/gumball-machine-test.ts b/contracts/tests/gumball-machine-test.ts index d0b251cd10a..f630664ac1f 100644 --- a/contracts/tests/gumball-machine-test.ts +++ b/contracts/tests/gumball-machine-test.ts @@ -32,13 +32,32 @@ import { OnChainGumballMachine, createDispenseNFTForSolIx, createDispenseNFTForTokensIx, - createAddConfigLinesIx, createUpdateConfigLinesIx, createDestroyGumballMachineIx, createInitializeGumballMachineIxs, createUpdateHeaderMetadataIx, getBubblegumAuthorityPDAKey, } from '../sdk/gumball-machine'; +import { + InitializeGumballMachineInstructionArgs, + createInitializeGumballMachineInstruction, + createAddConfigLinesInstruction, + createUpdateConfigLinesInstruction, + UpdateHeaderMetadataInstructionArgs, + UpdateConfigLinesInstructionArgs, + createUpdateHeaderMetadataInstruction, + createDestroyInstruction, + createDispenseNftSolInstruction, + createDispenseNftTokenInstruction +} from "../sdk/gumball-machine/src/generated/instructions"; +import { + val, + strToByteArray, + strToByteUint8Array +} from "../sdk/utils/index"; +import { + GumballMachineHeader +} from "../sdk/gumball-machine/src/generated/types/index"; import NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet"; import { getAssociatedTokenAddress, createMint, getOrCreateAssociatedTokenAccount, mintTo, getAccount } from "../../deps/solana-program-library/token/js/src"; import { @@ -55,6 +74,14 @@ let Bubblegum; let GummyrollProgramId; let BubblegumProgramId; +// TODO(sorend): port this to utils +function arrayEquals(a, b) { + return Array.isArray(a) && + Array.isArray(b) && + a.length === b.length && + a.every((val, index) => val === b[index]); +} + describe("gumball-machine", () => { // Configure the client to use the local cluster. @@ -77,17 +104,17 @@ describe("gumball-machine", () => { GummyrollProgramId = anchor.workspace.Gummyroll.programId; BubblegumProgramId = anchor.workspace.Bubblegum.programId; - function assertGumballMachineHeaderProperties(gm: OnChainGumballMachine, expectedHeader: InitGumballMachineProps) { + function assertGumballMachineHeaderProperties(gm: OnChainGumballMachine, expectedHeader: GumballMachineHeader) { assert( - gm.header.urlBase.equals(expectedHeader.urlBase), + arrayEquals(gm.header.urlBase, expectedHeader.urlBase), "Gumball Machine has incorrect url base" ); assert( - gm.header.nameBase.equals(expectedHeader.nameBase), + arrayEquals(gm.header.nameBase, expectedHeader.nameBase), "Gumball Machine has incorrect name base" ); assert( - gm.header.symbol.equals(expectedHeader.symbol), + arrayEquals(gm.header.symbol, expectedHeader.symbol), "Gumball Machine has incorrect symbol" ); assert( @@ -103,11 +130,11 @@ describe("gumball-machine", () => { "Gumball Machine has incorrect retainAuthority" ); assert( - gm.header.price.eq(expectedHeader.price), + val(gm.header.price).eq(val(expectedHeader.price)), "Gumball Machine has incorrect price" ); assert( - gm.header.goLiveDate.eq(expectedHeader.goLiveDate), + val(gm.header.goLiveDate).eq(val(expectedHeader.goLiveDate)), "Gumball Machine has incorrect goLiveDate" ); assert( @@ -135,17 +162,19 @@ describe("gumball-machine", () => { "Gumball Machine set with incorrect creatorAddress" ); assert( - gm.header.extensionLen.eq(expectedHeader.extensionLen), + val(gm.header.extensionLen).eq(val(expectedHeader.extensionLen)), "Gumball Machine has incorrect extensionLen" ); assert( - gm.header.maxMintSize.eq(expectedHeader.maxMintSize), + val(gm.header.maxMintSize).eq(val(expectedHeader.maxMintSize)), "Gumball Machine has incorrect maxMintSize" ); assert( - gm.header.maxItems.eq(expectedHeader.maxItems), + val(gm.header.maxItems).eq(val(expectedHeader.maxItems)), "Gumball Machine has incorrect max items" ); + + // TODO(sorend): add assertion on mint } function assertGumballMachineConfigProperties(gm: OnChainGumballMachine, expectedIndexArray: Buffer, expectedConfigLines: Buffer, onChainConfigLinesNumBytes: number) { @@ -170,27 +199,50 @@ describe("gumball-machine", () => { gumballMachineAcctSize: number, merkleRollKeypair: Keypair, merkleRollAccountSize: number, - desiredGumballMachineHeader: InitGumballMachineProps, - maxDepth: number, - maxBufferSize: number + gumballMachineInitArgs: InitializeGumballMachineInstructionArgs, + mint: PublicKey ) { const bubblegumAuthorityPDAKey = await getBubblegumAuthorityPDAKey(merkleRollKeypair.publicKey, BubblegumProgramId); - const initializeGumballMachineInstrs = await createInitializeGumballMachineIxs(payer, gumballMachineAcctKeypair, gumballMachineAcctSize, merkleRollKeypair, merkleRollAccountSize, desiredGumballMachineHeader, maxDepth, maxBufferSize, GummyrollProgramId, BubblegumProgramId, GumballMachine); + //const initializeGumballMachineInstr = await createInitializeGumballMachineInstruction() + const initializeGumballMachineInstrs = await createInitializeGumballMachineIxs(payer, gumballMachineAcctKeypair, gumballMachineAcctSize, merkleRollKeypair, merkleRollAccountSize, gumballMachineInitArgs, mint, GummyrollProgramId, BubblegumProgramId, GumballMachine); const tx = new Transaction(); initializeGumballMachineInstrs.forEach((instr) => tx.add(instr)); await GumballMachine.provider.send(tx, [payer, gumballMachineAcctKeypair, merkleRollKeypair], { commitment: "confirmed", }); - const tree = buildTree(Array(2 ** maxDepth).fill(Buffer.alloc(32))); - await assertOnChainMerkleRollProperties(GumballMachine.provider.connection, maxDepth, maxBufferSize, bubblegumAuthorityPDAKey, new PublicKey(tree.root), merkleRollKeypair.publicKey); + const tree = buildTree(Array(2 ** gumballMachineInitArgs.maxDepth).fill(Buffer.alloc(32))); + await assertOnChainMerkleRollProperties(GumballMachine.provider.connection, gumballMachineInitArgs.maxDepth, gumballMachineInitArgs.maxBufferSize, bubblegumAuthorityPDAKey, new PublicKey(tree.root), merkleRollKeypair.publicKey); const onChainGumballMachineAccount = await GumballMachine.provider.connection.getAccountInfo( gumballMachineAcctKeypair.publicKey ); const gumballMachine = decodeGumballMachine(onChainGumballMachineAccount.data, gumballMachineAcctSize); - assertGumballMachineHeaderProperties(gumballMachine, desiredGumballMachineHeader); + + let expectedOnChainHeader: GumballMachineHeader = { + urlBase: gumballMachineInitArgs.urlBase, + nameBase: gumballMachineInitArgs.nameBase, + symbol: gumballMachineInitArgs.symbol, + sellerFeeBasisPoints: gumballMachineInitArgs.sellerFeeBasisPoints, + isMutable: gumballMachineInitArgs.isMutable ? 1 : 0, + retainAuthority: gumballMachineInitArgs.retainAuthority ? 1 : 0, + padding: [0,0,0,0], + price: gumballMachineInitArgs.price, + goLiveDate: gumballMachineInitArgs.goLiveDate, + mint, + botWallet: gumballMachineInitArgs.botWallet, + receiver: gumballMachineInitArgs.receiver, + authority: gumballMachineInitArgs.authority, + collectionKey: gumballMachineInitArgs.collectionKey, // 0x0 -> no collection key + creatorAddress: payer.publicKey, + extensionLen: gumballMachineInitArgs.extensionLen, + maxMintSize: gumballMachineInitArgs.maxMintSize, + remaining: new BN(0), + maxItems: gumballMachineInitArgs.maxItems, + totalItemsAdded: new BN(0) + } + assertGumballMachineHeaderProperties(gumballMachine, expectedOnChainHeader); } async function addConfigLines( @@ -199,10 +251,18 @@ describe("gumball-machine", () => { gumballMachineAcctSize: number, gumballMachineAcctConfigIndexArrSize: number, gumballMachineAcctConfigLinesSize: number, - configLinesToAdd: Buffer, + configLinesToAdd: Uint8Array, allExpectedInitializedConfigLines: Buffer ) { - const addConfigLinesInstr = createAddConfigLinesIx(authority, gumballMachineAcctKey, configLinesToAdd, GumballMachine); + const addConfigLinesInstr = createAddConfigLinesInstruction( + { + gumballMachine: gumballMachineAcctKey, + authority: authority.publicKey + }, + { + newConfigLinesData: configLinesToAdd + } + ); const tx = new Transaction().add(addConfigLinesInstr) await GumballMachine.provider.send(tx, [authority], { commitment: "confirmed", @@ -216,7 +276,7 @@ describe("gumball-machine", () => { const expectedIndexArrBuffer = [...Array(gumballMachineAcctConfigIndexArrSize/4).keys()].reduce( (prevVal, curVal) => Buffer.concat([prevVal, Buffer.from(num32ToBuffer(curVal))]), Buffer.from([]) - ) + ); assertGumballMachineConfigProperties(gumballMachine, expectedIndexArrBuffer, allExpectedInitializedConfigLines, gumballMachineAcctConfigLinesSize); } @@ -231,7 +291,8 @@ describe("gumball-machine", () => { allExpectedInitializedConfigLines: Buffer, indexOfFirstLineToUpdate: BN ) { - const updateConfigLinesInstr = createUpdateConfigLinesIx(authority, gumballMachineAcctKey, updatedConfigLines, indexOfFirstLineToUpdate, GumballMachine); + const args: UpdateConfigLinesInstructionArgs = { startingLine: indexOfFirstLineToUpdate, newConfigLinesData: updatedConfigLines }; + const updateConfigLinesInstr = createUpdateConfigLinesIx(authority, gumballMachineAcctKey, args); const tx = new Transaction().add(updateConfigLinesInstr) await GumballMachine.provider.send(tx, [authority], { commitment: "confirmed", @@ -254,20 +315,19 @@ describe("gumball-machine", () => { authority: Keypair, gumballMachineAcctKey: PublicKey, gumballMachineAcctSize, - newHeader: InitGumballMachineProps, + newHeader: UpdateHeaderMetadataInstructionArgs, + resultingExpectedOnChainHeader: GumballMachineHeader ) { - const updateHeaderMetadataInstr = createUpdateHeaderMetadataIx(authority, gumballMachineAcctKey, newHeader, GumballMachine); - + const updateHeaderMetadataInstr = createUpdateHeaderMetadataIx(authority, gumballMachineAcctKey, newHeader); const tx = new Transaction().add(updateHeaderMetadataInstr) await GumballMachine.provider.send(tx, [authority], { commitment: "confirmed", }); - const onChainGumballMachineAccount = await GumballMachine.provider.connection.getAccountInfo( gumballMachineAcctKey ); const gumballMachine = decodeGumballMachine(onChainGumballMachineAccount.data, gumballMachineAcctSize); - assertGumballMachineHeaderProperties(gumballMachine, newHeader); + assertGumballMachineHeaderProperties(gumballMachine, resultingExpectedOnChainHeader); } async function dispenseCompressedNFTForSol( @@ -332,7 +392,7 @@ describe("gumball-machine", () => { ) { const originalGumballMachineAcctBalance = await connection.getBalance(gumballMachineAcctKeypair.publicKey); const originalAuthorityAcctBalance = await connection.getBalance(authorityKeypair.publicKey); - const destroyInstr = createDestroyGumballMachineIx(gumballMachineAcctKeypair, authorityKeypair, GumballMachine); + const destroyInstr = createDestroyGumballMachineIx(gumballMachineAcctKeypair, authorityKeypair); const tx = new Transaction().add(destroyInstr); await GumballMachine.provider.send(tx, [authorityKeypair], { commitment: "confirmed", @@ -351,7 +411,7 @@ describe("gumball-machine", () => { } describe("Testing gumball-machine", async () => { - let baseGumballMachineHeader: InitGumballMachineProps; + let baseGumballMachineInitProps: InitializeGumballMachineInstructionArgs; let creatorAddress: Keypair; let gumballMachineAcctKeypair: Keypair; let merkleRollKeypair: Keypair; @@ -401,24 +461,24 @@ describe("gumball-machine", () => { gumballMachineAcctKeypair = Keypair.generate(); merkleRollKeypair = Keypair.generate(); - baseGumballMachineHeader = { - urlBase: Buffer.from("https://arweave.net/Rmg4pcIv-0FQ7M7X838p2r592Q4NU63Fj7o7XsvBHEEl"), - nameBase: Buffer.from("zfgfsxrwieciemyavrpkuqehkmhqmnim"), - symbol: Buffer.from("12345678"), + baseGumballMachineInitProps = { + maxDepth: 3, + maxBufferSize: 8, + urlBase: strToByteArray("https://arweave.net/Rmg4pcIv-0FQ7M7X838p2r592Q4NU63Fj7o7XsvBHEEl"), + nameBase: strToByteArray("zfgfsxrwieciemyavrpkuqehkmhqmnim"), + symbol: strToByteArray("12345678"), sellerFeeBasisPoints: 100, isMutable: true, retainAuthority: true, price: new BN(10), goLiveDate: new BN(1234.0), - mint: NATIVE_MINT, botWallet: Keypair.generate().publicKey, receiver: creatorPaymentWallet.publicKey, authority: creatorAddress.publicKey, collectionKey: SystemProgram.programId, // 0x0 -> no collection key - creatorAddress: creatorAddress.publicKey, extensionLen: new BN(28), maxMintSize: new BN(10), - maxItems: new BN(250) + maxItems: new BN(250), }; // Give creator enough funds to produce accounts for NFT @@ -427,14 +487,14 @@ describe("gumball-machine", () => { "confirmed" ); - await initializeGumballMachine(creatorAddress, gumballMachineAcctKeypair, GUMBALL_MACHINE_ACCT_SIZE, merkleRollKeypair, MERKLE_ROLL_ACCT_SIZE, baseGumballMachineHeader, 3, 8); - await addConfigLines(creatorAddress, gumballMachineAcctKeypair.publicKey, GUMBALL_MACHINE_ACCT_SIZE, GUMBALL_MACHINE_ACCT_CONFIG_INDEX_ARRAY_SIZE, GUMBALL_MACHINE_ACCT_CONFIG_LINES_SIZE, Buffer.from("uluvnpwncgchwnbqfpbtdlcpdthc"), Buffer.from("uluvnpwncgchwnbqfpbtdlcpdthc")); + await initializeGumballMachine(creatorAddress, gumballMachineAcctKeypair, GUMBALL_MACHINE_ACCT_SIZE, merkleRollKeypair, MERKLE_ROLL_ACCT_SIZE, baseGumballMachineInitProps, NATIVE_MINT); + await addConfigLines(creatorAddress, gumballMachineAcctKeypair.publicKey, GUMBALL_MACHINE_ACCT_SIZE, GUMBALL_MACHINE_ACCT_CONFIG_INDEX_ARRAY_SIZE, GUMBALL_MACHINE_ACCT_CONFIG_LINES_SIZE, strToByteUint8Array("uluvnpwncgchwnbqfpbtdlcpdthc"), Buffer.from("uluvnpwncgchwnbqfpbtdlcpdthc")); }); describe("dispense nft sol instruction", async () => { beforeEach(async () => { // Give the recipient address enough money to not get rent exempt await GumballMachine.provider.connection.confirmTransaction( - await GumballMachine.provider.connection.requestAirdrop(baseGumballMachineHeader.receiver, LAMPORTS_PER_SOL), + await GumballMachine.provider.connection.requestAirdrop(baseGumballMachineInitProps.receiver, LAMPORTS_PER_SOL), "confirmed" ); @@ -450,7 +510,7 @@ describe("gumball-machine", () => { let dummyInstr; beforeEach(async () => { - dispenseNFTForSolInstr = await createDispenseNFTForSolIx(new BN(1), nftBuyer, baseGumballMachineHeader.receiver, gumballMachineAcctKeypair, merkleRollKeypair, noncePDAKey, GummyrollProgramId, BubblegumProgramId, GumballMachine); + dispenseNFTForSolInstr = await createDispenseNFTForSolIx(new BN(1), nftBuyer, baseGumballMachineInitProps.receiver, gumballMachineAcctKeypair, merkleRollKeypair, noncePDAKey, GummyrollProgramId, BubblegumProgramId, GumballMachine); dummyNewAcctKeypair = Keypair.generate(); dummyInstr = SystemProgram.createAccount({ fromPubkey: payer.publicKey, @@ -482,7 +542,7 @@ describe("gumball-machine", () => { it("Can dispense single NFT paid in sol", async () => { // Give the recipient address enough money to not get rent exempt await GumballMachine.provider.connection.confirmTransaction( - await GumballMachine.provider.connection.requestAirdrop(baseGumballMachineHeader.receiver, LAMPORTS_PER_SOL), + await GumballMachine.provider.connection.requestAirdrop(baseGumballMachineInitProps.receiver, LAMPORTS_PER_SOL), "confirmed" ); @@ -493,21 +553,21 @@ describe("gumball-machine", () => { ); const nftBuyerBalanceBeforePurchase = await connection.getBalance(nftBuyer.publicKey); - const creatorBalanceBeforePurchase = await connection.getBalance(baseGumballMachineHeader.receiver); + const creatorBalanceBeforePurchase = await connection.getBalance(baseGumballMachineInitProps.receiver); // Purchase the compressed NFT with SOL - await dispenseCompressedNFTForSol(new BN(1), nftBuyer, baseGumballMachineHeader.receiver, gumballMachineAcctKeypair, merkleRollKeypair, noncePDAKey); + await dispenseCompressedNFTForSol(new BN(1), nftBuyer, baseGumballMachineInitProps.receiver, gumballMachineAcctKeypair, merkleRollKeypair, noncePDAKey); const nftBuyerBalanceAfterPurchase = await connection.getBalance(nftBuyer.publicKey); - const creatorBalanceAfterPurchase = await connection.getBalance(baseGumballMachineHeader.receiver); + const creatorBalanceAfterPurchase = await connection.getBalance(baseGumballMachineInitProps.receiver); // Assert on how the creator and buyer's balances changed assert( - await creatorBalanceAfterPurchase === (creatorBalanceBeforePurchase + baseGumballMachineHeader.price.toNumber()), + await creatorBalanceAfterPurchase === (creatorBalanceBeforePurchase + val(baseGumballMachineInitProps.price).toNumber()), "Creator balance did not update as expected after NFT purchase" ); assert( - await nftBuyerBalanceAfterPurchase === (nftBuyerBalanceBeforePurchase - baseGumballMachineHeader.price.toNumber()), + await nftBuyerBalanceAfterPurchase === (nftBuyerBalanceBeforePurchase - val(baseGumballMachineInitProps.price).toNumber()), "NFT purchaser balance did not decrease as expected after NFT purchase" ); }); @@ -518,33 +578,49 @@ describe("gumball-machine", () => { await updateConfigLines(creatorAddress, gumballMachineAcctKeypair.publicKey, GUMBALL_MACHINE_ACCT_SIZE, GUMBALL_MACHINE_ACCT_CONFIG_INDEX_ARRAY_SIZE, GUMBALL_MACHINE_ACCT_CONFIG_LINES_SIZE, Buffer.from("aaavnpwncgchwnbqfpbtdlcpdaaa"), Buffer.from("aaavnpwncgchwnbqfpbtdlcpdaaa"), new BN(0)); }); it("Can update gumball header", async () => { - const newGumballMachineHeader: InitGumballMachineProps = { - urlBase: Buffer.from("https://arweave.net/bzdjillretjcraaxawlnhqrhmexzbsixyajrlzhfcvcc"), - nameBase: Buffer.from("wmqeslreeondhmcmtfebrwqnqcoasbye"), - symbol: Buffer.from("abcdefgh"), + const newGumballMachineHeader: UpdateHeaderMetadataInstructionArgs = { + urlBase: strToByteArray("https://arweave.net/bzdjillretjcraaxawlnhqrhmexzbsixyajrlzhfcvcc"), + nameBase: strToByteArray("wmqeslreeondhmcmtfebrwqnqcoasbye"), + symbol: strToByteArray("abcdefgh"), sellerFeeBasisPoints: 50, isMutable: false, retainAuthority: false, price: new BN(100), goLiveDate: new BN(5678.0), - mint: baseGumballMachineHeader.mint, // Cannot be modified after init botWallet: Keypair.generate().publicKey, - receiver: baseGumballMachineHeader.receiver, // FOR NOW: Cannot be modified after init authority: Keypair.generate().publicKey, - collectionKey: baseGumballMachineHeader.collectionKey, // Cannot be modified after init - creatorAddress: baseGumballMachineHeader.creatorAddress, // Cannot be modified after init - extensionLen: baseGumballMachineHeader.extensionLen, // Cannot be modified after init - maxMintSize: new BN(15), - maxItems: baseGumballMachineHeader.maxItems // Cannot be modified after init + maxMintSize: new BN(15) }; - await updateHeaderMetadata(creatorAddress, gumballMachineAcctKeypair.publicKey, GUMBALL_MACHINE_ACCT_SIZE, newGumballMachineHeader); + + const expectedOnChainHeader: GumballMachineHeader = { + urlBase: newGumballMachineHeader.urlBase, + nameBase: newGumballMachineHeader.nameBase, + symbol: newGumballMachineHeader.symbol, + sellerFeeBasisPoints: newGumballMachineHeader.sellerFeeBasisPoints, + isMutable: newGumballMachineHeader.isMutable ? 1 : 0, + retainAuthority: newGumballMachineHeader.retainAuthority ? 1 : 0, + padding: [0,0,0,0], + price: newGumballMachineHeader.price, + goLiveDate: newGumballMachineHeader.goLiveDate, + mint: NATIVE_MINT, + botWallet: newGumballMachineHeader.botWallet, + receiver: baseGumballMachineInitProps.receiver, + authority: newGumballMachineHeader.authority, + collectionKey: baseGumballMachineInitProps.collectionKey, + creatorAddress: creatorAddress.publicKey, + extensionLen: baseGumballMachineInitProps.extensionLen, + maxMintSize: newGumballMachineHeader.maxMintSize, + remaining: new BN(0), + maxItems: baseGumballMachineInitProps.maxItems, + totalItemsAdded: new BN(0) + } + await updateHeaderMetadata(creatorAddress, gumballMachineAcctKeypair.publicKey, GUMBALL_MACHINE_ACCT_SIZE, newGumballMachineHeader, expectedOnChainHeader); }); it("Can destroy gumball machine and reclaim lamports", async () => { await destroyGumballMachine(gumballMachineAcctKeypair, creatorAddress); }); }); }); - describe("spl token projects", async () => { let someMint: PublicKey; let creatorReceiverTokenAccount; @@ -566,28 +642,28 @@ describe("gumball-machine", () => { someMint = await createMint(connection, payer, payer.publicKey, null, 9); creatorReceiverTokenAccount = await getOrCreateAssociatedTokenAccount(connection, payer, someMint, creatorAddress.publicKey); - - baseGumballMachineHeader = { - urlBase: Buffer.from("https://arweave.net/Rmg4pcIv-0FQ7M7X838p2r592Q4NU63Fj7o7XsvBHEEl"), - nameBase: Buffer.from("zfgfsxrwieciemyavrpkuqehkmhqmnim"), - symbol: Buffer.from("12345678"), + + baseGumballMachineInitProps = { + maxDepth: 3, + maxBufferSize: 8, + urlBase: strToByteArray("https://arweave.net/Rmg4pcIv-0FQ7M7X838p2r592Q4NU63Fj7o7XsvBHEEl"), + nameBase: strToByteArray("zfgfsxrwieciemyavrpkuqehkmhqmnim"), + symbol: strToByteArray("12345678"), sellerFeeBasisPoints: 100, isMutable: true, retainAuthority: true, price: new BN(10), goLiveDate: new BN(1234.0), - mint: someMint, botWallet: botWallet.publicKey, receiver: creatorReceiverTokenAccount.address, authority: creatorAddress.publicKey, - collectionKey: SystemProgram.programId, // 0x0 -> no collection - creatorAddress: creatorAddress.publicKey, + collectionKey: SystemProgram.programId, // 0x0 -> no collection key extensionLen: new BN(28), maxMintSize: new BN(10), - maxItems: new BN(250) + maxItems: new BN(250), }; - await initializeGumballMachine(creatorAddress, gumballMachineAcctKeypair, GUMBALL_MACHINE_ACCT_SIZE, merkleRollKeypair, MERKLE_ROLL_ACCT_SIZE, baseGumballMachineHeader, 3, 8); + await initializeGumballMachine(creatorAddress, gumballMachineAcctKeypair, GUMBALL_MACHINE_ACCT_SIZE, merkleRollKeypair, MERKLE_ROLL_ACCT_SIZE, baseGumballMachineInitProps, someMint); await addConfigLines(creatorAddress, gumballMachineAcctKeypair.publicKey, GUMBALL_MACHINE_ACCT_SIZE, GUMBALL_MACHINE_ACCT_CONFIG_INDEX_ARRAY_SIZE, GUMBALL_MACHINE_ACCT_CONFIG_LINES_SIZE, Buffer.from("uluvnpwncgchwnbqfpbtdlcpdthc" + "aauvnpwncgchwnbqfpbtdlcpdthc"), Buffer.from("uluvnpwncgchwnbqfpbtdlcpdthc" + "aauvnpwncgchwnbqfpbtdlcpdthc")); // Create and fund the NFT pruchaser @@ -637,12 +713,12 @@ describe("gumball-machine", () => { let newBuyerTokenAccount = await getAccount(connection, nftBuyerTokenAccount.address); assert( - Number(newCreatorTokenAccount.amount) === Number(creatorReceiverTokenAccount.amount) + baseGumballMachineHeader.price.toNumber(), + Number(newCreatorTokenAccount.amount) === Number(creatorReceiverTokenAccount.amount) + val(baseGumballMachineInitProps.price).toNumber(), "The creator did not receive their payment as expected" ); assert( - Number(newBuyerTokenAccount.amount) === Number(buyerTokenAccount.amount) - baseGumballMachineHeader.price.toNumber(), + Number(newBuyerTokenAccount.amount) === Number(buyerTokenAccount.amount) - val(baseGumballMachineInitProps.price).toNumber(), "The nft buyer did not pay for the nft as expected" ); @@ -654,12 +730,12 @@ describe("gumball-machine", () => { newBuyerTokenAccount = await getAccount(connection, nftBuyerTokenAccount.address); assert( - Number(newCreatorTokenAccount.amount) === Number(creatorReceiverTokenAccount.amount) + baseGumballMachineHeader.price.toNumber(), + Number(newCreatorTokenAccount.amount) === Number(creatorReceiverTokenAccount.amount) + val(baseGumballMachineInitProps.price).toNumber(), "The creator did not receive their payment as expected" ); assert( - Number(newBuyerTokenAccount.amount) === Number(buyerTokenAccount.amount) - baseGumballMachineHeader.price.toNumber(), + Number(newBuyerTokenAccount.amount) === Number(buyerTokenAccount.amount) - val(baseGumballMachineInitProps.price).toNumber(), "The nft buyer did not pay for the nft as expected" ); }); diff --git a/contracts/yarn.lock b/contracts/yarn.lock index b577fa72637..31675b78b30 100644 --- a/contracts/yarn.lock +++ b/contracts/yarn.lock @@ -113,32 +113,6 @@ bn.js "^5.2.0" debug "^4.3.3" -"@metaplex-foundation/rustbin@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/rustbin/-/rustbin-0.3.1.tgz#bbcd61e8699b73c0b062728c6f5e8d52e8145042" - integrity sha512-hWd2JPrnt2/nJzkBpZD3Y6ZfCUlJujv2K7qUfsxdS0jSwLrSrOvYwmNWFw6mc3lbULj6VP4WDyuy9W5/CHU/lQ== - dependencies: - debug "^4.3.3" - semver "^7.3.7" - text-table "^0.2.0" - toml "^3.0.0" - -"@metaplex-foundation/solita@^0.8.2": - version "0.8.2" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/solita/-/solita-0.8.2.tgz#09674105be58aea7c76b31fd1d9888866c0e0203" - integrity sha512-YCypBul8CMnm6YeVR9GRJQiCRrnWdYAYcx50v7rz7gn+XdhSVLv1daQNwx8gBfYJtKYWAu9aVTp5SKw8dynCxQ== - dependencies: - "@metaplex-foundation/beet" "^0.2.0" - "@metaplex-foundation/beet-solana" "^0.1.1" - "@metaplex-foundation/rustbin" "^0.3.0" - "@solana/web3.js" "^1.36.0" - camelcase "^6.2.1" - debug "^4.3.3" - js-sha256 "^0.9.0" - prettier "^2.5.1" - snake-case "^3.0.4" - spok "^1.4.3" - "@project-serum/anchor@^0.21.0": version "0.21.0" resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.21.0.tgz#ad5fb33744991ec1900cdb2fd22707c908b12b5f" @@ -313,28 +287,6 @@ superstruct "^0.14.2" tweetnacl "^1.0.0" -"@solana/web3.js@^1.36.0": - version "1.43.4" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.43.4.tgz#cb38e3e3fe1195195017d5e5453ecced6cffc259" - integrity sha512-9+c965R3vjIRIfUFQtKfaG8BM4tVoo/fp4DvmqHAGLTaeHilVsRdyXszW6+Ues5KczgBejlp62k2SeUcbOibUg== - dependencies: - "@babel/runtime" "^7.12.5" - "@ethersproject/sha2" "^5.5.0" - "@solana/buffer-layout" "^4.0.0" - bigint-buffer "^1.1.5" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.1" - fast-stable-stringify "^1.0.0" - jayson "^3.4.4" - js-sha3 "^0.8.0" - node-fetch "2" - rpc-websockets "^7.4.2" - secp256k1 "^4.0.2" - superstruct "^0.14.2" - tweetnacl "^1.0.0" - "@solana/web3.js@^1.37.0": version "1.37.0" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.37.0.tgz#167b5b5d4aedc151237d9230b6142da068b0af34" @@ -455,7 +407,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansicolors@^0.3.2, ansicolors@~0.3.2: +ansicolors@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= @@ -642,7 +594,7 @@ camelcase@^5.3.1: resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0, camelcase@^6.2.1: +camelcase@^6.0.0: version "6.3.0" resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -1211,13 +1163,6 @@ lower-case@^2.0.2: dependencies: tslib "^2.0.3" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - make-error@^1.1.1: version "1.3.6" resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" @@ -1325,18 +1270,18 @@ node-addon-api@^2.0.0: resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== -node-fetch@2, node-fetch@2.6.7: +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.1: - version "2.6.1" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== - node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: version "4.3.0" resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz" @@ -1419,11 +1364,6 @@ picomatch@^2.0.4, picomatch@^2.2.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -prettier@^2.5.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" - integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== - ps-tree@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" @@ -1497,13 +1437,6 @@ secp256k1@^4.0.2: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -semver@^7.3.7: - version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== - dependencies: - lru-cache "^6.0.0" - serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" @@ -1561,13 +1494,6 @@ split@0.3: dependencies: through "2" -spok@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/spok/-/spok-1.4.3.tgz#8516234e6bd8caf0e10567bd675e15fd03b5ceb8" - integrity sha512-5wFGctwrk638aDs+44u99kohxFNByUq2wo0uShQ9yqxSmsxqx7zKbMo1Busy4s7stZQXU+PhJ/BlVf2XWFEGIw== - dependencies: - ansicolors "~0.3.2" - start-server-and-test@^1.14.0: version "1.14.0" resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.14.0.tgz#c57f04f73eac15dd51733b551d775b40837fdde3" @@ -1643,11 +1569,6 @@ text-encoding-utf-8@^1.0.2: resolved "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz" integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - through@2, "through@>=2.2.7 <3", through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" @@ -1821,11 +1742,6 @@ y18n@^5.0.5: resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" From 1d3df44288855f74106584f36eb6d97e92af44d0 Mon Sep 17 00:00:00 2001 From: Sam Orend Date: Tue, 7 Jun 2022 00:30:25 -0400 Subject: [PATCH 7/8] cleanup --- .../sdk/gumball-machine/accounts/index.ts | 53 +-------- contracts/sdk/gumball-machine/index.ts | 1 + .../sdk/gumball-machine/instructions/index.ts | 101 +----------------- contracts/sdk/gumball-machine/package.json | 2 +- contracts/sdk/gumball-machine/types/index.ts | 29 +---- contracts/tests/gumball-machine-test.ts | 65 ++++++----- 6 files changed, 40 insertions(+), 211 deletions(-) diff --git a/contracts/sdk/gumball-machine/accounts/index.ts b/contracts/sdk/gumball-machine/accounts/index.ts index e5efb739f58..4933ce03bd3 100644 --- a/contracts/sdk/gumball-machine/accounts/index.ts +++ b/contracts/sdk/gumball-machine/accounts/index.ts @@ -10,31 +10,6 @@ export type OnChainGumballMachine = { configData: ConfigData } -export const GUMBALL_MACHINE_HEADER_SIZE = 360; - -/*type GumballMachineHeader = { - urlBase: Buffer, // [u8; 64] - nameBase: Buffer, // [u8; 32] - symbol: Buffer, // [u8; 8] - sellerFeeBasisPoints: number, // u16 - isMutable: boolean, // u8 - retainAuthority: boolean, // u8 - _padding: Buffer, // [u8; 4], - price: BN, // u64 - goLiveDate: BN, // i64 - mint: PublicKey, - botWallet: PublicKey, - receiver: PublicKey, - authority: PublicKey, - collectionKey: PublicKey, - creatorAddress: PublicKey, - extensionLen: BN, // usize - maxMintSize: BN, // u64 - remaining: BN, // usize - maxItems: BN, // u64 - totalItemsAdded: BN, // usize -}*/ - type ConfigData = { indexArray: Buffer, configLines: Buffer @@ -46,34 +21,10 @@ export function decodeGumballMachine(buffer: Buffer, accountSize: number): OnCha let postHeaderOffset: number; [header, postHeaderOffset] = gumballMachineHeaderBeet.deserialize(buffer); - // Deserialize header - // TODO(sorend): remove - /*let header: GumballMachineHeader = { - urlBase: Array.from(reader.readFixedArray(64)), - nameBase: Array.from(reader.readFixedArray(32)), - symbol: Array.from(reader.readFixedArray(8)), - sellerFeeBasisPoints: reader.readU16(), - isMutable: reader.readU8(), - retainAuthority: reader.readU8(), - padding: Array.from(reader.readFixedArray(4)), - price: reader.readU64(), - goLiveDate: new BN(reader.readFixedArray(8), null, 'le'), - mint: readPublicKey(reader), - botWallet: readPublicKey(reader), - receiver: readPublicKey(reader), - authority: readPublicKey(reader), - collectionKey: readPublicKey(reader), - creatorAddress: readPublicKey(reader), - extensionLen: new BN(reader.readFixedArray(8), null, 'le'), - maxMintSize: reader.readU64(), - remaining: new BN(reader.readFixedArray(8), null, 'le'), - maxItems: reader.readU64(), - totalItemsAdded: new BN(reader.readFixedArray(8), null, 'le'), - };*/ - // Deserailize indices and config section let reader = new borsh.BinaryReader(Buffer.from(buffer)); - // TODO(sorend): nicer would be nice but the Buffer API is not the best + + // Read past the header bytes, it would be cleaner to start the buffer at the postHeaderOffset, but could not quickly find right functions reader.readFixedArray(postHeaderOffset); let numIndexArrayBytes = 4 * val(header.maxItems).toNumber(); let numConfigBytes = val(header.extensionLen).toNumber() * val(header.maxItems).toNumber(); diff --git a/contracts/sdk/gumball-machine/index.ts b/contracts/sdk/gumball-machine/index.ts index bf5086a4f0a..8d6b9ea50d2 100644 --- a/contracts/sdk/gumball-machine/index.ts +++ b/contracts/sdk/gumball-machine/index.ts @@ -2,3 +2,4 @@ export * from './instructions'; export * from './accounts'; export * from './types'; export * from './utils'; +export * from './src/generated/index' diff --git a/contracts/sdk/gumball-machine/instructions/index.ts b/contracts/sdk/gumball-machine/instructions/index.ts index 905d98f59c3..996cc1dab20 100644 --- a/contracts/sdk/gumball-machine/instructions/index.ts +++ b/contracts/sdk/gumball-machine/instructions/index.ts @@ -8,24 +8,13 @@ import { SYSVAR_SLOT_HASHES_PUBKEY, TransactionInstruction, } from "@solana/web3.js"; -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - NATIVE_MINT - } from "@solana/spl-token"; import { GumballMachine, - InitGumballMachineProps } from '../types'; import { InitializeGumballMachineInstructionArgs, - UpdateHeaderMetadataInstructionArgs, - UpdateConfigLinesInstructionArgs, createInitializeGumballMachineInstruction, createDispenseNftSolInstruction, - createUpdateHeaderMetadataInstruction, - createDestroyInstruction, - createUpdateConfigLinesInstruction, createDispenseNftTokenInstruction } from "../src/generated"; import { @@ -34,9 +23,8 @@ import { } from '../utils'; /** - * Client side function to faciliate the creation of instructions for: initialize_gumball_machine - * Handles the creation of merkle roll + gumball machine accounts and the initialization of the gumball machine header - * with props from InitializeGumballMachineInstructionArgs, -> see ../src/generated/instructions/initializeGumballMachine.ts for details + * Wrapper on top of Solita's createInitializeGumballMachineInstruction + * Produces a series of instructions to create the merkle roll + gumball machine accounts and initialize gumball machine * */ export async function createInitializeGumballMachineIxs( payer: Keypair, @@ -93,27 +81,7 @@ export async function createInitializeGumballMachineIxs( } /** - * Client side function to create instruction for: update_header_metadata - * Enables the gumball machine authority to update config parameters in the GumballMachine header - * */ -export function createUpdateHeaderMetadataIx( - authority: Keypair, - gumballMachineAcctKey: PublicKey, - updateHeaderArgs: UpdateHeaderMetadataInstructionArgs, -): TransactionInstruction { - const updateHeaderMetadataInstr = createUpdateHeaderMetadataInstruction( - { - gumballMachine: gumballMachineAcctKey, - authority: authority.publicKey - }, - updateHeaderArgs - ); - return updateHeaderMetadataInstr; -} - -/** - * Client side function to create instruction: dispense_nft_sol. - * Enables payer to purchase a compressed NFT from a project seeking SOL + * Wrapper on top of Solita's createDispenseNftSolInstruction. Automatically fetches necessary PDA keys for instruction * */ export async function createDispenseNFTForSolIx( numNFTs: BN, @@ -151,8 +119,7 @@ export async function createDispenseNFTForSolIx( } /** - * Client side function to create instruction: dispense_nft_token. - * Enables payer to purchase a compressed NFT from a project seeking SPL tokens + * Wrapper on top of Solita's createDispenseNftTokenInstruction. Automatically fetches necessary PDA keys for instruction * */ export async function createDispenseNFTForTokensIx( numNFTs: BN, @@ -188,64 +155,4 @@ export async function createDispenseNFTForTokensIx( } ); return dispenseInstr; -} - -/** - * Client side function to create instruction: add_config_lines. - * Enables gumballMachine authority to add config lines -> compressed NFTs that can be minted - * */ -/*export function createAddConfigLinesIx( - authority: Keypair, - gumballMachineAcctKey: PublicKey, - configLinesToAdd: Buffer, - gumballMachine: Program -): TransactionInstruction { - const addConfigLinesInstr = gumballMachine.instruction.addConfigLines( - configLinesToAdd, - { - accounts: { - gumballMachine: gumballMachineAcctKey, - authority: authority.publicKey - }, - signers: [authority] - } - ) - return addConfigLinesInstr; -}*/ - -/** - * Client side function to create instruction: destroy - * Enables authority for a GumballMachine to pull all lamports out of their GumballMachine account - * effectively "destroying" the GumballMachine for use and returning their funds - * */ -export function createDestroyGumballMachineIx( - gumballMachineAcctKeypair: Keypair, - authorityKeypair: Keypair - ): TransactionInstruction { - const destroyInstr = createDestroyInstruction( - { - gumballMachine: gumballMachineAcctKeypair.publicKey, - authority: authorityKeypair.publicKey - } - ); - return destroyInstr; -} - -/** - * Client side function to create instruction: update_config_lines - * Enables authority to update the data stored in certain config lines which have already been added to their GumballMachine - * */ -export function createUpdateConfigLinesIx( - authority: Keypair, - gumballMachineAcctKey: PublicKey, - args: UpdateConfigLinesInstructionArgs -): TransactionInstruction { - const updateConfigLinesInstr = createUpdateConfigLinesInstruction( - { - gumballMachine: gumballMachineAcctKey, - authority: authority.publicKey - }, - args - ); - return updateConfigLinesInstr; } \ No newline at end of file diff --git a/contracts/sdk/gumball-machine/package.json b/contracts/sdk/gumball-machine/package.json index 9b91acef2cb..62afbda5064 100644 --- a/contracts/sdk/gumball-machine/package.json +++ b/contracts/sdk/gumball-machine/package.json @@ -1,7 +1,7 @@ { "name": "gumball-machine", "version": "1.0.0", - "main": "index.js", + "main": "index.ts", "license": "MIT", "dependencies": { "@metaplex-foundation/rustbin": "^0.3.1", diff --git a/contracts/sdk/gumball-machine/types/index.ts b/contracts/sdk/gumball-machine/types/index.ts index 3f8e8927ea5..5764cfc0605 100644 --- a/contracts/sdk/gumball-machine/types/index.ts +++ b/contracts/sdk/gumball-machine/types/index.ts @@ -1,28 +1 @@ -import { BN } from "@project-serum/anchor"; -import { - PublicKey, -} from "@solana/web3.js"; - -export { GumballMachine } from "../../../target/types/gumball_machine"; - -// @notice: This type is only used to facilitate creating the initialize_gumball_machine instruction on the client side, -// it is not related to deserailizing onchain GumballMachine accounts. See ../instructions/index.ts for usage -export type InitGumballMachineProps = { - urlBase: Buffer, - nameBase: Buffer, - symbol: Buffer, - sellerFeeBasisPoints: number, - isMutable: boolean, - retainAuthority: boolean, - price: BN, - goLiveDate: BN, - mint: PublicKey, - botWallet: PublicKey, - receiver: PublicKey, - authority: PublicKey, - collectionKey: PublicKey, - creatorAddress: PublicKey, - extensionLen: BN, - maxMintSize: BN, - maxItems: BN -} \ No newline at end of file +export { GumballMachine } from "../../../target/types/gumball_machine"; \ No newline at end of file diff --git a/contracts/tests/gumball-machine-test.ts b/contracts/tests/gumball-machine-test.ts index f630664ac1f..3060566eaf0 100644 --- a/contracts/tests/gumball-machine-test.ts +++ b/contracts/tests/gumball-machine-test.ts @@ -1,54 +1,38 @@ import * as anchor from "@project-serum/anchor"; -import { keccak_256 } from "js-sha3"; import { BN, Provider, Program } from "@project-serum/anchor"; import { Bubblegum } from "../target/types/bubblegum"; -import { Gummyroll } from "../target/types/gummyroll"; -import { Key, PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata"; import { PublicKey, Keypair, SystemProgram, Transaction, Connection as web3Connection, - SYSVAR_RENT_PUBKEY, - SYSVAR_INSTRUCTIONS_PUBKEY, - SYSVAR_SLOT_HASHES_PUBKEY, LAMPORTS_PER_SOL, - TransactionInstruction, } from "@solana/web3.js"; import { assert } from "chai"; -import { buildTree, Tree } from "./merkle-tree"; +import { buildTree } from "./merkle-tree"; import { - decodeMerkleRoll, getMerkleRollAccountSize, assertOnChainMerkleRollProperties } from "../sdk/gummyroll"; import { - GUMBALL_MACHINE_HEADER_SIZE, GumballMachine, - InitGumballMachineProps, decodeGumballMachine, OnChainGumballMachine, createDispenseNFTForSolIx, createDispenseNFTForTokensIx, - createUpdateConfigLinesIx, - createDestroyGumballMachineIx, createInitializeGumballMachineIxs, - createUpdateHeaderMetadataIx, getBubblegumAuthorityPDAKey, } from '../sdk/gumball-machine'; import { InitializeGumballMachineInstructionArgs, - createInitializeGumballMachineInstruction, createAddConfigLinesInstruction, createUpdateConfigLinesInstruction, UpdateHeaderMetadataInstructionArgs, UpdateConfigLinesInstructionArgs, createUpdateHeaderMetadataInstruction, createDestroyInstruction, - createDispenseNftSolInstruction, - createDispenseNftTokenInstruction } from "../sdk/gumball-machine/src/generated/instructions"; import { val, @@ -56,13 +40,12 @@ import { strToByteUint8Array } from "../sdk/utils/index"; import { - GumballMachineHeader + GumballMachineHeader, + gumballMachineHeaderBeet } from "../sdk/gumball-machine/src/generated/types/index"; import NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet"; -import { getAssociatedTokenAddress, createMint, getOrCreateAssociatedTokenAccount, mintTo, getAccount } from "../../deps/solana-program-library/token/js/src"; +import { createMint, getOrCreateAssociatedTokenAccount, mintTo, getAccount } from "../../deps/solana-program-library/token/js/src"; import { - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, NATIVE_MINT } from "@solana/spl-token"; import { logTx, num32ToBuffer } from "./utils"; @@ -161,6 +144,10 @@ describe("gumball-machine", () => { gm.header.creatorAddress.equals(expectedHeader.creatorAddress), "Gumball Machine set with incorrect creatorAddress" ); + assert( + gm.header.mint.equals(expectedHeader.mint), + "Gumball Machine set with incorrect mint" + ); assert( val(gm.header.extensionLen).eq(val(expectedHeader.extensionLen)), "Gumball Machine has incorrect extensionLen" @@ -173,8 +160,6 @@ describe("gumball-machine", () => { val(gm.header.maxItems).eq(val(expectedHeader.maxItems)), "Gumball Machine has incorrect max items" ); - - // TODO(sorend): add assertion on mint } function assertGumballMachineConfigProperties(gm: OnChainGumballMachine, expectedIndexArray: Buffer, expectedConfigLines: Buffer, onChainConfigLinesNumBytes: number) { @@ -203,7 +188,6 @@ describe("gumball-machine", () => { mint: PublicKey ) { const bubblegumAuthorityPDAKey = await getBubblegumAuthorityPDAKey(merkleRollKeypair.publicKey, BubblegumProgramId); - //const initializeGumballMachineInstr = await createInitializeGumballMachineInstruction() const initializeGumballMachineInstrs = await createInitializeGumballMachineIxs(payer, gumballMachineAcctKeypair, gumballMachineAcctSize, merkleRollKeypair, merkleRollAccountSize, gumballMachineInitArgs, mint, GummyrollProgramId, BubblegumProgramId, GumballMachine); const tx = new Transaction(); initializeGumballMachineInstrs.forEach((instr) => tx.add(instr)); @@ -292,7 +276,13 @@ describe("gumball-machine", () => { indexOfFirstLineToUpdate: BN ) { const args: UpdateConfigLinesInstructionArgs = { startingLine: indexOfFirstLineToUpdate, newConfigLinesData: updatedConfigLines }; - const updateConfigLinesInstr = createUpdateConfigLinesIx(authority, gumballMachineAcctKey, args); + const updateConfigLinesInstr = createUpdateConfigLinesInstruction( + { + authority: authority.publicKey, + gumballMachine: gumballMachineAcctKey, + }, + args + ); const tx = new Transaction().add(updateConfigLinesInstr) await GumballMachine.provider.send(tx, [authority], { commitment: "confirmed", @@ -318,7 +308,13 @@ describe("gumball-machine", () => { newHeader: UpdateHeaderMetadataInstructionArgs, resultingExpectedOnChainHeader: GumballMachineHeader ) { - const updateHeaderMetadataInstr = createUpdateHeaderMetadataIx(authority, gumballMachineAcctKey, newHeader); + const updateHeaderMetadataInstr = createUpdateHeaderMetadataInstruction( + { + gumballMachine: gumballMachineAcctKey, + authority: authority.publicKey + }, + newHeader + ); const tx = new Transaction().add(updateHeaderMetadataInstr) await GumballMachine.provider.send(tx, [authority], { commitment: "confirmed", @@ -352,9 +348,7 @@ describe("gumball-machine", () => { const tx = new Transaction().add(dispenseInstr); await GumballMachine.provider.send(tx, [payer], { commitment: "confirmed", - }); - - // TODO(sorend): assert that the effects of the mint are as expected + }); } async function dispenseCompressedNFTForTokens( @@ -381,9 +375,7 @@ describe("gumball-machine", () => { const tx = new Transaction().add(dispenseInstr); await GumballMachine.provider.send(tx, [payer], { commitment: "confirmed", - }); - - // TODO(sorend): assert that the effects of the mint are as expected + }); } async function destroyGumballMachine( @@ -392,7 +384,12 @@ describe("gumball-machine", () => { ) { const originalGumballMachineAcctBalance = await connection.getBalance(gumballMachineAcctKeypair.publicKey); const originalAuthorityAcctBalance = await connection.getBalance(authorityKeypair.publicKey); - const destroyInstr = createDestroyGumballMachineIx(gumballMachineAcctKeypair, authorityKeypair); + const destroyInstr = createDestroyInstruction( + { + gumballMachine: gumballMachineAcctKeypair.publicKey, + authority: authorityKeypair.publicKey + } + ); const tx = new Transaction().add(destroyInstr); await GumballMachine.provider.send(tx, [authorityKeypair], { commitment: "confirmed", @@ -419,7 +416,7 @@ describe("gumball-machine", () => { let nftBuyer: Keypair; const GUMBALL_MACHINE_ACCT_CONFIG_INDEX_ARRAY_SIZE = 1000; const GUMBALL_MACHINE_ACCT_CONFIG_LINES_SIZE = 7000; - const GUMBALL_MACHINE_ACCT_SIZE = GUMBALL_MACHINE_HEADER_SIZE + GUMBALL_MACHINE_ACCT_CONFIG_INDEX_ARRAY_SIZE + GUMBALL_MACHINE_ACCT_CONFIG_LINES_SIZE; + const GUMBALL_MACHINE_ACCT_SIZE = gumballMachineHeaderBeet.byteSize + GUMBALL_MACHINE_ACCT_CONFIG_INDEX_ARRAY_SIZE + GUMBALL_MACHINE_ACCT_CONFIG_LINES_SIZE; const MERKLE_ROLL_ACCT_SIZE = getMerkleRollAccountSize(3,8); before(async () => { From 9cc4c16042bec57c29115ee7b4f7ef7ea3d72862 Mon Sep 17 00:00:00 2001 From: Sam Orend Date: Tue, 7 Jun 2022 11:44:12 -0400 Subject: [PATCH 8/8] cleanup --- contracts/sdk/gumball-machine/instructions/index.ts | 2 -- contracts/tests/gumball-machine-test.ts | 10 +--------- contracts/tests/utils.ts | 6 ++++++ 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/contracts/sdk/gumball-machine/instructions/index.ts b/contracts/sdk/gumball-machine/instructions/index.ts index 996cc1dab20..6f323925e72 100644 --- a/contracts/sdk/gumball-machine/instructions/index.ts +++ b/contracts/sdk/gumball-machine/instructions/index.ts @@ -76,7 +76,6 @@ export async function createInitializeGumballMachineIxs( }, gumballMachineInitArgs ); - // initGumballMachineInstr.keys maybe initGumballMachineInstr.keys[].isSigner = true return [allocGumballMachineAcctInstr, allocMerkleRollAcctInstr, initGumballMachineInstr]; } @@ -101,7 +100,6 @@ export async function createDispenseNFTForSolIx( gumballMachine: gumballMachineAcctKeypair.publicKey, payer: payer.publicKey, receiver: receiver, - //systemProgram: SystemProgram.programId, willyWonka: willyWonkaPDAKey, recentBlockhashes: SYSVAR_SLOT_HASHES_PUBKEY, instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY, diff --git a/contracts/tests/gumball-machine-test.ts b/contracts/tests/gumball-machine-test.ts index 3060566eaf0..37846eff8d9 100644 --- a/contracts/tests/gumball-machine-test.ts +++ b/contracts/tests/gumball-machine-test.ts @@ -48,7 +48,7 @@ import { createMint, getOrCreateAssociatedTokenAccount, mintTo, getAccount } fro import { NATIVE_MINT } from "@solana/spl-token"; -import { logTx, num32ToBuffer } from "./utils"; +import { logTx, num32ToBuffer, arrayEquals } from "./utils"; // @ts-ignore let GumballMachine; @@ -57,14 +57,6 @@ let Bubblegum; let GummyrollProgramId; let BubblegumProgramId; -// TODO(sorend): port this to utils -function arrayEquals(a, b) { - return Array.isArray(a) && - Array.isArray(b) && - a.length === b.length && - a.every((val, index) => val === b[index]); -} - describe("gumball-machine", () => { // Configure the client to use the local cluster. diff --git a/contracts/tests/utils.ts b/contracts/tests/utils.ts index 9fbc8bca11a..c728bb466e8 100644 --- a/contracts/tests/utils.ts +++ b/contracts/tests/utils.ts @@ -40,3 +40,9 @@ export function num32ToBuffer(num: number) { return Buffer.from([byte1, byte2, byte3, byte4]) } +export function arrayEquals(a, b) { + return Array.isArray(a) && + Array.isArray(b) && + a.length === b.length && + a.every((val, index) => val === b[index]); +}