From 03353e3a30060c4d3399266697fc6dde5abce6a2 Mon Sep 17 00:00:00 2001 From: tiago Date: Thu, 31 Jul 2025 12:07:58 +0100 Subject: [PATCH 1/9] Added Client Libs: TLV-Account-Resolution, EBALTS, ABL. Integrated into the SDK and CLI --- packages/abl/README.md | 0 packages/abl/codama.json | 12 + packages/abl/idl/abl_srfc37.json | 532 ++++++++++++++++++ packages/abl/jest.config.js | 29 + packages/abl/package.json | 51 ++ .../abl/src/generated/accounts/aBWallet.ts | 126 +++++ packages/abl/src/generated/accounts/index.ts | 10 + .../abl/src/generated/accounts/listConfig.ts | 154 +++++ .../abl/src/generated/errors/ablSrfc37.ts | 68 +++ packages/abl/src/generated/errors/index.ts | 9 + packages/abl/src/generated/index.ts | 13 + .../generated/instructions/addWalletToList.ts | 235 ++++++++ .../instructions/canFreezePermissionless.ts | 115 ++++ .../instructions/canThawPermissionless.ts | 256 +++++++++ .../abl/src/generated/instructions/index.ts | 15 + .../instructions/initializeListConfig.ts | 239 ++++++++ .../instructions/removeWalletFromList.ts | 227 ++++++++ .../instructions/setExtraMetasThaw.ts | 381 +++++++++++++ .../src/generated/instructions/setListMode.ts | 199 +++++++ .../abl/src/generated/programs/ablSrfc37.ts | 184 ++++++ packages/abl/src/generated/programs/index.ts | 9 + packages/abl/src/generated/shared/index.ts | 164 ++++++ packages/abl/src/generated/types/index.ts | 9 + packages/abl/src/generated/types/mode.ts | 36 ++ packages/abl/src/index.ts | 53 ++ packages/abl/tsconfig.json | 10 + packages/cli/package.json | 3 + packages/cli/src/commands/abl/abl.ts | 7 + packages/cli/src/commands/abl/createList.ts | 82 +++ .../cli/src/commands/abl/setExtraMetas.ts | 83 +++ packages/cli/src/commands/abl/utils.ts | 4 + .../cli/src/commands/create/arcade-token.ts | 4 +- .../cli/src/commands/ebalts/createConfig.ts | 94 ++++ packages/cli/src/commands/ebalts/ebalts.ts | 11 + .../ebalts/enablePermissionlessThaw.ts | 88 +++ .../src/commands/ebalts/setGatingProgram.ts | 96 ++++ .../src/commands/ebalts/thawPermissionless.ts | 104 ++++ packages/cli/src/commands/ebalts/util.ts | 4 + packages/cli/src/index.ts | 6 +- packages/ebalts/README.md | 0 packages/ebalts/jest.config.js | 29 + packages/ebalts/package.json | 51 ++ .../ebalts/src/generated/accounts/index.ts | 9 + .../src/generated/accounts/mintConfig.ts | 169 ++++++ packages/ebalts/src/generated/index.ts | 12 + .../generated/instructions/createConfig.ts | 262 +++++++++ .../instructions/forfeitFreezeAuthority.ts | 235 ++++++++ .../src/generated/instructions/freeze.ts | 225 ++++++++ .../instructions/freezePermissionless.ts | 261 +++++++++ .../src/generated/instructions/index.ts | 17 + .../generated/instructions/setAuthority.ts | 188 +++++++ .../instructions/setGatingProgram.ts | 188 +++++++ .../ebalts/src/generated/instructions/thaw.ts | 225 ++++++++ .../instructions/thawPermissionless.ts | 258 +++++++++ .../togglePermissionlessInstructions.ts | 205 +++++++ .../generated/pdas/freezeExtraMetasAccount.ts | 35 ++ packages/ebalts/src/generated/pdas/index.ts | 11 + .../ebalts/src/generated/pdas/mintConfig.ts | 35 ++ .../generated/pdas/thawExtraMetasAccount.ts | 35 ++ .../ebalts/src/generated/programs/ebalts.ts | 123 ++++ .../ebalts/src/generated/programs/index.ts | 9 + packages/ebalts/src/generated/shared/index.ts | 164 ++++++ packages/ebalts/src/index.ts | 104 ++++ packages/ebalts/tsconfig.json | 10 + packages/sdk/package.json | 5 +- packages/sdk/src/abl/createList.ts | 51 ++ packages/sdk/src/abl/index.ts | 3 + packages/sdk/src/abl/setExtraMetas.ts | 50 ++ packages/sdk/src/abl/utils.ts | 4 + packages/sdk/src/ebalts/createConfig.ts | 56 ++ .../src/ebalts/enablePermissionlessThaw.ts | 45 ++ packages/sdk/src/ebalts/index.ts | 7 + packages/sdk/src/ebalts/setGatingProgram.ts | 47 ++ packages/sdk/src/ebalts/thawPermissionless.ts | 72 +++ packages/sdk/src/ebalts/utils.ts | 4 + packages/sdk/src/index.ts | 2 + packages/sdk/src/issuance/createMint.ts | 2 +- packages/sdk/src/templates/arcadeToken.ts | 2 +- packages/tlv-account-resolution/README.md | 0 .../tlv-account-resolution/jest.config.js | 29 + packages/tlv-account-resolution/package.json | 50 ++ packages/tlv-account-resolution/src/errors.ts | 96 ++++ packages/tlv-account-resolution/src/index.ts | 4 + .../tlv-account-resolution/src/pubkeyData.ts | 63 +++ packages/tlv-account-resolution/src/seeds.ts | 134 +++++ packages/tlv-account-resolution/src/state.ts | 147 +++++ packages/tlv-account-resolution/tsconfig.json | 10 + pnpm-lock.yaml | 402 ++++++++++++- tsconfig.json | 5 +- 89 files changed, 7854 insertions(+), 18 deletions(-) create mode 100644 packages/abl/README.md create mode 100644 packages/abl/codama.json create mode 100644 packages/abl/idl/abl_srfc37.json create mode 100644 packages/abl/jest.config.js create mode 100644 packages/abl/package.json create mode 100644 packages/abl/src/generated/accounts/aBWallet.ts create mode 100644 packages/abl/src/generated/accounts/index.ts create mode 100644 packages/abl/src/generated/accounts/listConfig.ts create mode 100644 packages/abl/src/generated/errors/ablSrfc37.ts create mode 100644 packages/abl/src/generated/errors/index.ts create mode 100644 packages/abl/src/generated/index.ts create mode 100644 packages/abl/src/generated/instructions/addWalletToList.ts create mode 100644 packages/abl/src/generated/instructions/canFreezePermissionless.ts create mode 100644 packages/abl/src/generated/instructions/canThawPermissionless.ts create mode 100644 packages/abl/src/generated/instructions/index.ts create mode 100644 packages/abl/src/generated/instructions/initializeListConfig.ts create mode 100644 packages/abl/src/generated/instructions/removeWalletFromList.ts create mode 100644 packages/abl/src/generated/instructions/setExtraMetasThaw.ts create mode 100644 packages/abl/src/generated/instructions/setListMode.ts create mode 100644 packages/abl/src/generated/programs/ablSrfc37.ts create mode 100644 packages/abl/src/generated/programs/index.ts create mode 100644 packages/abl/src/generated/shared/index.ts create mode 100644 packages/abl/src/generated/types/index.ts create mode 100644 packages/abl/src/generated/types/mode.ts create mode 100644 packages/abl/src/index.ts create mode 100644 packages/abl/tsconfig.json create mode 100644 packages/cli/src/commands/abl/abl.ts create mode 100644 packages/cli/src/commands/abl/createList.ts create mode 100644 packages/cli/src/commands/abl/setExtraMetas.ts create mode 100644 packages/cli/src/commands/abl/utils.ts create mode 100644 packages/cli/src/commands/ebalts/createConfig.ts create mode 100644 packages/cli/src/commands/ebalts/ebalts.ts create mode 100644 packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts create mode 100644 packages/cli/src/commands/ebalts/setGatingProgram.ts create mode 100644 packages/cli/src/commands/ebalts/thawPermissionless.ts create mode 100644 packages/cli/src/commands/ebalts/util.ts create mode 100644 packages/ebalts/README.md create mode 100644 packages/ebalts/jest.config.js create mode 100644 packages/ebalts/package.json create mode 100644 packages/ebalts/src/generated/accounts/index.ts create mode 100644 packages/ebalts/src/generated/accounts/mintConfig.ts create mode 100644 packages/ebalts/src/generated/index.ts create mode 100644 packages/ebalts/src/generated/instructions/createConfig.ts create mode 100644 packages/ebalts/src/generated/instructions/forfeitFreezeAuthority.ts create mode 100644 packages/ebalts/src/generated/instructions/freeze.ts create mode 100644 packages/ebalts/src/generated/instructions/freezePermissionless.ts create mode 100644 packages/ebalts/src/generated/instructions/index.ts create mode 100644 packages/ebalts/src/generated/instructions/setAuthority.ts create mode 100644 packages/ebalts/src/generated/instructions/setGatingProgram.ts create mode 100644 packages/ebalts/src/generated/instructions/thaw.ts create mode 100644 packages/ebalts/src/generated/instructions/thawPermissionless.ts create mode 100644 packages/ebalts/src/generated/instructions/togglePermissionlessInstructions.ts create mode 100644 packages/ebalts/src/generated/pdas/freezeExtraMetasAccount.ts create mode 100644 packages/ebalts/src/generated/pdas/index.ts create mode 100644 packages/ebalts/src/generated/pdas/mintConfig.ts create mode 100644 packages/ebalts/src/generated/pdas/thawExtraMetasAccount.ts create mode 100644 packages/ebalts/src/generated/programs/ebalts.ts create mode 100644 packages/ebalts/src/generated/programs/index.ts create mode 100644 packages/ebalts/src/generated/shared/index.ts create mode 100644 packages/ebalts/src/index.ts create mode 100644 packages/ebalts/tsconfig.json create mode 100644 packages/sdk/src/abl/createList.ts create mode 100644 packages/sdk/src/abl/index.ts create mode 100644 packages/sdk/src/abl/setExtraMetas.ts create mode 100644 packages/sdk/src/abl/utils.ts create mode 100644 packages/sdk/src/ebalts/createConfig.ts create mode 100644 packages/sdk/src/ebalts/enablePermissionlessThaw.ts create mode 100644 packages/sdk/src/ebalts/index.ts create mode 100644 packages/sdk/src/ebalts/setGatingProgram.ts create mode 100644 packages/sdk/src/ebalts/thawPermissionless.ts create mode 100644 packages/sdk/src/ebalts/utils.ts create mode 100644 packages/tlv-account-resolution/README.md create mode 100644 packages/tlv-account-resolution/jest.config.js create mode 100644 packages/tlv-account-resolution/package.json create mode 100644 packages/tlv-account-resolution/src/errors.ts create mode 100644 packages/tlv-account-resolution/src/index.ts create mode 100644 packages/tlv-account-resolution/src/pubkeyData.ts create mode 100644 packages/tlv-account-resolution/src/seeds.ts create mode 100644 packages/tlv-account-resolution/src/state.ts create mode 100644 packages/tlv-account-resolution/tsconfig.json diff --git a/packages/abl/README.md b/packages/abl/README.md new file mode 100644 index 0000000..e69de29 diff --git a/packages/abl/codama.json b/packages/abl/codama.json new file mode 100644 index 0000000..ec13733 --- /dev/null +++ b/packages/abl/codama.json @@ -0,0 +1,12 @@ +{ + "idl": "idl/abl_srfc37.json", + "before": [], + "scripts": { + "js": { + "from": "@codama/renderers-js", + "args": [ + "src/generated/" + ] + } + } +} \ No newline at end of file diff --git a/packages/abl/idl/abl_srfc37.json b/packages/abl/idl/abl_srfc37.json new file mode 100644 index 0000000..3f6e7d0 --- /dev/null +++ b/packages/abl/idl/abl_srfc37.json @@ -0,0 +1,532 @@ +{ + "address": "8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N", + "metadata": { + "name": "abl_srfc37", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "add_wallet_to_list", + "discriminator": [ + 249, + 25, + 0, + 35, + 88, + 124, + 60, + 201 + ], + "accounts": [ + { + "name": "authority", + "writable": true, + "signer": true, + "relations": [ + "list_config" + ] + }, + { + "name": "list_config" + }, + { + "name": "ab_wallet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "list_config.seed", + "account": "ListConfig" + }, + { + "kind": "arg", + "path": "wallet" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "wallet", + "type": "pubkey" + } + ] + }, + { + "name": "can_freeze_permissionless", + "discriminator": [ + 214, + 141, + 109, + 75, + 248, + 1, + 45, + 29 + ], + "accounts": [], + "args": [] + }, + { + "name": "can_thaw_permissionless", + "discriminator": [ + 8, + 175, + 169, + 129, + 137, + 74, + 61, + 241 + ], + "accounts": [ + { + "name": "authority" + }, + { + "name": "token_account" + }, + { + "name": "mint" + }, + { + "name": "owner" + }, + { + "name": "extra_metas" + }, + { + "name": "list_config" + }, + { + "name": "ab_wallet" + } + ], + "args": [] + }, + { + "name": "initialize_list_config", + "discriminator": [ + 201, + 223, + 17, + 210, + 208, + 124, + 101, + 58 + ], + "accounts": [ + { + "name": "authority", + "writable": true, + "signer": true + }, + { + "name": "list_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 108, + 105, + 115, + 116, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "authority" + }, + { + "kind": "arg", + "path": "args.seed" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "args", + "type": { + "defined": { + "name": "InitializeListConfigArgs" + } + } + } + ] + }, + { + "name": "remove_wallet_from_list", + "discriminator": [ + 185, + 14, + 13, + 222, + 207, + 118, + 221, + 146 + ], + "accounts": [ + { + "name": "authority", + "writable": true, + "signer": true, + "relations": [ + "list_config" + ] + }, + { + "name": "list_config" + }, + { + "name": "ab_wallet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "list_config.seed", + "account": "ListConfig" + }, + { + "kind": "account", + "path": "ab_wallet.wallet", + "account": "ABWallet" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "set_extra_metas_thaw", + "discriminator": [ + 6, + 94, + 201, + 255, + 159, + 241, + 169, + 164 + ], + "accounts": [ + { + "name": "authority", + "writable": true, + "signer": true + }, + { + "name": "list_config" + }, + { + "name": "ebalts_mint_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 77, + 73, + 78, + 84, + 95, + 67, + 79, + 78, + 70, + 73, + 71 + ] + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 202, + 3, + 2, + 25, + 133, + 31, + 219, + 239, + 24, + 84, + 179, + 198, + 92, + 76, + 228, + 172, + 204, + 14, + 138, + 90, + 35, + 151, + 49, + 178, + 41, + 166, + 250, + 0, + 0, + 0, + 0, + 0 + ] + } + } + }, + { + "name": "mint" + }, + { + "name": "extra_metas_thaw", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 116, + 104, + 97, + 119, + 95, + 101, + 120, + 116, + 114, + 97, + 95, + 97, + 99, + 99, + 111, + 117, + 110, + 116, + 95, + 109, + 101, + 116, + 97, + 115 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "set_list_mode", + "discriminator": [ + 174, + 19, + 169, + 240, + 19, + 9, + 146, + 12 + ], + "accounts": [ + { + "name": "authority", + "writable": true, + "signer": true, + "relations": [ + "list_config" + ] + }, + { + "name": "list_config" + } + ], + "args": [ + { + "name": "mode", + "type": { + "defined": { + "name": "Mode" + } + } + } + ] + } + ], + "accounts": [ + { + "name": "ABWallet", + "discriminator": [ + 111, + 162, + 31, + 45, + 79, + 239, + 198, + 72 + ] + }, + { + "name": "ListConfig", + "discriminator": [ + 9, + 220, + 3, + 74, + 122, + 218, + 71, + 204 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "InvalidAuthority" + }, + { + "code": 6001, + "name": "NotSupported" + }, + { + "code": 6002, + "name": "InvalidMintConfig" + }, + { + "code": 6003, + "name": "InvalidABWallet" + }, + { + "code": 6004, + "name": "Unauthorized" + } + ], + "types": [ + { + "name": "ABWallet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "wallet", + "type": "pubkey" + } + ] + } + }, + { + "name": "InitializeListConfigArgs", + "type": { + "kind": "struct", + "fields": [ + { + "name": "seed", + "type": "pubkey" + }, + { + "name": "mode", + "type": { + "defined": { + "name": "Mode" + } + } + } + ] + } + }, + { + "name": "ListConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "seed", + "type": "pubkey" + }, + { + "name": "mode", + "type": { + "defined": { + "name": "Mode" + } + } + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "Mode", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Allow" + }, + { + "name": "AllowWithPermissionlessEOAs" + }, + { + "name": "Block" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/abl/jest.config.js b/packages/abl/jest.config.js new file mode 100644 index 0000000..38e2b68 --- /dev/null +++ b/packages/abl/jest.config.js @@ -0,0 +1,29 @@ +/** @type {import('jest').Config} */ +export default { + preset: 'ts-jest/presets/default-esm', + extensionsToTreatAsEsm: ['.ts'], + testEnvironment: 'node', + roots: ['/src'], + testMatch: ['**/__tests__/**/*.test.ts', '**/?(*.)+(spec|test).ts'], + transform: { + '^.+\\.ts$': [ + 'ts-jest', + { + useESM: true, + }, + ], + }, + collectCoverageFrom: [ + 'src/**/*.ts', + '!src/**/*.d.ts', + '!src/**/__tests__/**/*.test.ts', + '!src/**/*.test.ts', + '!src/**/__tests__/setup.ts', + '!src/**/__tests__/test-utils.ts', + ], + moduleNameMapper: { + '^@/(.*)$': '/src/$1', + }, + moduleFileExtensions: ['ts', 'js', 'json'], + setupFilesAfterEnv: ['/src/__tests__/setup.ts'], +}; diff --git a/packages/abl/package.json b/packages/abl/package.json new file mode 100644 index 0000000..58b470f --- /dev/null +++ b/packages/abl/package.json @@ -0,0 +1,51 @@ +{ + "name": "@mosaic/abl", + "version": "0.1.0", + "description": "SDK for Mosaic with helper functions for issuance and management of any token", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsc", + "dev": "echo 'Dev will be implemented'", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "lint": "eslint src --ext .ts", + "lint:fix": "eslint src --ext .ts --fix", + "type-check": "tsc --noEmit", + "clean": "rm -rf dist" + }, + "dependencies": { + "gill": "^0.10.2", + "@solana/kit": "2.3.0" + }, + "devDependencies": { + "@types/jest": "^29.5.0", + "@typescript-eslint/eslint-plugin": "^8.34.0", + "@codama/cli": "1.2.1", + "@typescript-eslint/parser": "^8.34.0", + "eslint": "^9.32.0", + "jest": "^29.5.0", + "ts-jest": "^29.1.0" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "keywords": [ + "solana", + "token-2022", + "extensions", + "core", + "hooks" + ] +} diff --git a/packages/abl/src/generated/accounts/aBWallet.ts b/packages/abl/src/generated/accounts/aBWallet.ts new file mode 100644 index 0000000..ea12b48 --- /dev/null +++ b/packages/abl/src/generated/accounts/aBWallet.ts @@ -0,0 +1,126 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + assertAccountExists, + assertAccountsExist, + combineCodec, + decodeAccount, + fetchEncodedAccount, + fetchEncodedAccounts, + fixDecoderSize, + fixEncoderSize, + getAddressDecoder, + getAddressEncoder, + getBytesDecoder, + getBytesEncoder, + getStructDecoder, + getStructEncoder, + transformEncoder, + type Account, + type Address, + type EncodedAccount, + type FetchAccountConfig, + type FetchAccountsConfig, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, + type MaybeAccount, + type MaybeEncodedAccount, + type ReadonlyUint8Array, +} from '@solana/kit'; + +export const A_B_WALLET_DISCRIMINATOR = new Uint8Array([ + 111, 162, 31, 45, 79, 239, 198, 72, +]); + +export function getABWalletDiscriminatorBytes() { + return fixEncoderSize(getBytesEncoder(), 8).encode(A_B_WALLET_DISCRIMINATOR); +} + +export type ABWallet = { discriminator: ReadonlyUint8Array; wallet: Address }; + +export type ABWalletArgs = { wallet: Address }; + +export function getABWalletEncoder(): FixedSizeEncoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', fixEncoderSize(getBytesEncoder(), 8)], + ['wallet', getAddressEncoder()], + ]), + (value) => ({ ...value, discriminator: A_B_WALLET_DISCRIMINATOR }) + ); +} + +export function getABWalletDecoder(): FixedSizeDecoder { + return getStructDecoder([ + ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], + ['wallet', getAddressDecoder()], + ]); +} + +export function getABWalletCodec(): FixedSizeCodec { + return combineCodec(getABWalletEncoder(), getABWalletDecoder()); +} + +export function decodeABWallet( + encodedAccount: EncodedAccount +): Account; +export function decodeABWallet( + encodedAccount: MaybeEncodedAccount +): MaybeAccount; +export function decodeABWallet( + encodedAccount: EncodedAccount | MaybeEncodedAccount +): Account | MaybeAccount { + return decodeAccount( + encodedAccount as MaybeEncodedAccount, + getABWalletDecoder() + ); +} + +export async function fetchABWallet( + rpc: Parameters[0], + address: Address, + config?: FetchAccountConfig +): Promise> { + const maybeAccount = await fetchMaybeABWallet(rpc, address, config); + assertAccountExists(maybeAccount); + return maybeAccount; +} + +export async function fetchMaybeABWallet( + rpc: Parameters[0], + address: Address, + config?: FetchAccountConfig +): Promise> { + const maybeAccount = await fetchEncodedAccount(rpc, address, config); + return decodeABWallet(maybeAccount); +} + +export async function fetchAllABWallet( + rpc: Parameters[0], + addresses: Array
, + config?: FetchAccountsConfig +): Promise[]> { + const maybeAccounts = await fetchAllMaybeABWallet(rpc, addresses, config); + assertAccountsExist(maybeAccounts); + return maybeAccounts; +} + +export async function fetchAllMaybeABWallet( + rpc: Parameters[0], + addresses: Array
, + config?: FetchAccountsConfig +): Promise[]> { + const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config); + return maybeAccounts.map((maybeAccount) => decodeABWallet(maybeAccount)); +} + +export function getABWalletSize(): number { + return 40; +} diff --git a/packages/abl/src/generated/accounts/index.ts b/packages/abl/src/generated/accounts/index.ts new file mode 100644 index 0000000..bfb3597 --- /dev/null +++ b/packages/abl/src/generated/accounts/index.ts @@ -0,0 +1,10 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './aBWallet'; +export * from './listConfig'; diff --git a/packages/abl/src/generated/accounts/listConfig.ts b/packages/abl/src/generated/accounts/listConfig.ts new file mode 100644 index 0000000..5e2b9e3 --- /dev/null +++ b/packages/abl/src/generated/accounts/listConfig.ts @@ -0,0 +1,154 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + assertAccountExists, + assertAccountsExist, + combineCodec, + decodeAccount, + fetchEncodedAccount, + fetchEncodedAccounts, + fixDecoderSize, + fixEncoderSize, + getAddressDecoder, + getAddressEncoder, + getBytesDecoder, + getBytesEncoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Account, + type Address, + type EncodedAccount, + type FetchAccountConfig, + type FetchAccountsConfig, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, + type MaybeAccount, + type MaybeEncodedAccount, + type ReadonlyUint8Array, +} from '@solana/kit'; +import { + getModeDecoder, + getModeEncoder, + type Mode, + type ModeArgs, +} from '../types'; + +export const LIST_CONFIG_DISCRIMINATOR = new Uint8Array([ + 9, 220, 3, 74, 122, 218, 71, 204, +]); + +export function getListConfigDiscriminatorBytes() { + return fixEncoderSize(getBytesEncoder(), 8).encode(LIST_CONFIG_DISCRIMINATOR); +} + +export type ListConfig = { + discriminator: ReadonlyUint8Array; + authority: Address; + seed: Address; + mode: Mode; + bump: number; +}; + +export type ListConfigArgs = { + authority: Address; + seed: Address; + mode: ModeArgs; + bump: number; +}; + +export function getListConfigEncoder(): FixedSizeEncoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', fixEncoderSize(getBytesEncoder(), 8)], + ['authority', getAddressEncoder()], + ['seed', getAddressEncoder()], + ['mode', getModeEncoder()], + ['bump', getU8Encoder()], + ]), + (value) => ({ ...value, discriminator: LIST_CONFIG_DISCRIMINATOR }) + ); +} + +export function getListConfigDecoder(): FixedSizeDecoder { + return getStructDecoder([ + ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], + ['authority', getAddressDecoder()], + ['seed', getAddressDecoder()], + ['mode', getModeDecoder()], + ['bump', getU8Decoder()], + ]); +} + +export function getListConfigCodec(): FixedSizeCodec< + ListConfigArgs, + ListConfig +> { + return combineCodec(getListConfigEncoder(), getListConfigDecoder()); +} + +export function decodeListConfig( + encodedAccount: EncodedAccount +): Account; +export function decodeListConfig( + encodedAccount: MaybeEncodedAccount +): MaybeAccount; +export function decodeListConfig( + encodedAccount: EncodedAccount | MaybeEncodedAccount +): Account | MaybeAccount { + return decodeAccount( + encodedAccount as MaybeEncodedAccount, + getListConfigDecoder() + ); +} + +export async function fetchListConfig( + rpc: Parameters[0], + address: Address, + config?: FetchAccountConfig +): Promise> { + const maybeAccount = await fetchMaybeListConfig(rpc, address, config); + assertAccountExists(maybeAccount); + return maybeAccount; +} + +export async function fetchMaybeListConfig( + rpc: Parameters[0], + address: Address, + config?: FetchAccountConfig +): Promise> { + const maybeAccount = await fetchEncodedAccount(rpc, address, config); + return decodeListConfig(maybeAccount); +} + +export async function fetchAllListConfig( + rpc: Parameters[0], + addresses: Array
, + config?: FetchAccountsConfig +): Promise[]> { + const maybeAccounts = await fetchAllMaybeListConfig(rpc, addresses, config); + assertAccountsExist(maybeAccounts); + return maybeAccounts; +} + +export async function fetchAllMaybeListConfig( + rpc: Parameters[0], + addresses: Array
, + config?: FetchAccountsConfig +): Promise[]> { + const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config); + return maybeAccounts.map((maybeAccount) => decodeListConfig(maybeAccount)); +} + +export function getListConfigSize(): number { + return 74; +} diff --git a/packages/abl/src/generated/errors/ablSrfc37.ts b/packages/abl/src/generated/errors/ablSrfc37.ts new file mode 100644 index 0000000..3b0d852 --- /dev/null +++ b/packages/abl/src/generated/errors/ablSrfc37.ts @@ -0,0 +1,68 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + isProgramError, + type Address, + type SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM, + type SolanaError, +} from '@solana/kit'; +import { ABL_SRFC37_PROGRAM_ADDRESS } from '../programs'; + +/** InvalidAuthority: */ +export const ABL_SRFC37_ERROR__INVALID_AUTHORITY = 0x1770; // 6000 +/** NotSupported: */ +export const ABL_SRFC37_ERROR__NOT_SUPPORTED = 0x1771; // 6001 +/** InvalidMintConfig: */ +export const ABL_SRFC37_ERROR__INVALID_MINT_CONFIG = 0x1772; // 6002 +/** InvalidABWallet: */ +export const ABL_SRFC37_ERROR__INVALID_A_B_WALLET = 0x1773; // 6003 +/** Unauthorized: */ +export const ABL_SRFC37_ERROR__UNAUTHORIZED = 0x1774; // 6004 + +export type AblSrfc37Error = + | typeof ABL_SRFC37_ERROR__INVALID_A_B_WALLET + | typeof ABL_SRFC37_ERROR__INVALID_AUTHORITY + | typeof ABL_SRFC37_ERROR__INVALID_MINT_CONFIG + | typeof ABL_SRFC37_ERROR__NOT_SUPPORTED + | typeof ABL_SRFC37_ERROR__UNAUTHORIZED; + +let ablSrfc37ErrorMessages: Record | undefined; +if (process.env.NODE_ENV !== 'production') { + ablSrfc37ErrorMessages = { + [ABL_SRFC37_ERROR__INVALID_A_B_WALLET]: ``, + [ABL_SRFC37_ERROR__INVALID_AUTHORITY]: ``, + [ABL_SRFC37_ERROR__INVALID_MINT_CONFIG]: ``, + [ABL_SRFC37_ERROR__NOT_SUPPORTED]: ``, + [ABL_SRFC37_ERROR__UNAUTHORIZED]: ``, + }; +} + +export function getAblSrfc37ErrorMessage(code: AblSrfc37Error): string { + if (process.env.NODE_ENV !== 'production') { + return (ablSrfc37ErrorMessages as Record)[code]; + } + + return 'Error message not available in production bundles.'; +} + +export function isAblSrfc37Error( + error: unknown, + transactionMessage: { + instructions: Record; + }, + code?: TProgramErrorCode +): error is SolanaError & + Readonly<{ context: Readonly<{ code: TProgramErrorCode }> }> { + return isProgramError( + error, + transactionMessage, + ABL_SRFC37_PROGRAM_ADDRESS, + code + ); +} diff --git a/packages/abl/src/generated/errors/index.ts b/packages/abl/src/generated/errors/index.ts new file mode 100644 index 0000000..e8d71dd --- /dev/null +++ b/packages/abl/src/generated/errors/index.ts @@ -0,0 +1,9 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './ablSrfc37'; diff --git a/packages/abl/src/generated/index.ts b/packages/abl/src/generated/index.ts new file mode 100644 index 0000000..02964a6 --- /dev/null +++ b/packages/abl/src/generated/index.ts @@ -0,0 +1,13 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './accounts'; +export * from './errors'; +export * from './instructions'; +export * from './programs'; +export * from './types'; diff --git a/packages/abl/src/generated/instructions/addWalletToList.ts b/packages/abl/src/generated/instructions/addWalletToList.ts new file mode 100644 index 0000000..510027d --- /dev/null +++ b/packages/abl/src/generated/instructions/addWalletToList.ts @@ -0,0 +1,235 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + fixDecoderSize, + fixEncoderSize, + getAddressDecoder, + getAddressEncoder, + getBytesDecoder, + getBytesEncoder, + getStructDecoder, + getStructEncoder, + transformEncoder, + type AccountMeta, + type AccountSignerMeta, + type Address, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, + type Instruction, + type InstructionWithAccounts, + type InstructionWithData, + type ReadonlyAccount, + type ReadonlyUint8Array, + type TransactionSigner, + type WritableAccount, + type WritableSignerAccount, +} from '@solana/kit'; +import { ABL_SRFC37_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const ADD_WALLET_TO_LIST_DISCRIMINATOR = new Uint8Array([ + 249, 25, 0, 35, 88, 124, 60, 201, +]); + +export function getAddWalletToListDiscriminatorBytes() { + return fixEncoderSize(getBytesEncoder(), 8).encode( + ADD_WALLET_TO_LIST_DISCRIMINATOR + ); +} + +export type AddWalletToListInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountAuthority extends string | AccountMeta = string, + TAccountListConfig extends string | AccountMeta = string, + TAccountAbWallet extends string | AccountMeta = string, + TAccountSystemProgram extends + | string + | AccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly AccountMeta[] = [], +> = Instruction & + InstructionWithData & + InstructionWithAccounts< + [ + TAccountAuthority extends string + ? WritableSignerAccount & + AccountSignerMeta + : TAccountAuthority, + TAccountListConfig extends string + ? ReadonlyAccount + : TAccountListConfig, + TAccountAbWallet extends string + ? WritableAccount + : TAccountAbWallet, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type AddWalletToListInstructionData = { + discriminator: ReadonlyUint8Array; + wallet: Address; +}; + +export type AddWalletToListInstructionDataArgs = { wallet: Address }; + +export function getAddWalletToListInstructionDataEncoder(): FixedSizeEncoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', fixEncoderSize(getBytesEncoder(), 8)], + ['wallet', getAddressEncoder()], + ]), + (value) => ({ ...value, discriminator: ADD_WALLET_TO_LIST_DISCRIMINATOR }) + ); +} + +export function getAddWalletToListInstructionDataDecoder(): FixedSizeDecoder { + return getStructDecoder([ + ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], + ['wallet', getAddressDecoder()], + ]); +} + +export function getAddWalletToListInstructionDataCodec(): FixedSizeCodec< + AddWalletToListInstructionDataArgs, + AddWalletToListInstructionData +> { + return combineCodec( + getAddWalletToListInstructionDataEncoder(), + getAddWalletToListInstructionDataDecoder() + ); +} + +export type AddWalletToListInput< + TAccountAuthority extends string = string, + TAccountListConfig extends string = string, + TAccountAbWallet extends string = string, + TAccountSystemProgram extends string = string, +> = { + authority: TransactionSigner; + listConfig: Address; + abWallet: Address; + systemProgram?: Address; + wallet: AddWalletToListInstructionDataArgs['wallet']; +}; + +export function getAddWalletToListInstruction< + TAccountAuthority extends string, + TAccountListConfig extends string, + TAccountAbWallet extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof ABL_SRFC37_PROGRAM_ADDRESS, +>( + input: AddWalletToListInput< + TAccountAuthority, + TAccountListConfig, + TAccountAbWallet, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): AddWalletToListInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountAbWallet, + TAccountSystemProgram +> { + // Program address. + const programAddress = config?.programAddress ?? ABL_SRFC37_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: true }, + listConfig: { value: input.listConfig ?? null, isWritable: false }, + abWallet: { value: input.abWallet ?? null, isWritable: true }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Resolve default values. + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.listConfig), + getAccountMeta(accounts.abWallet), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getAddWalletToListInstructionDataEncoder().encode( + args as AddWalletToListInstructionDataArgs + ), + } as AddWalletToListInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountAbWallet, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedAddWalletToListInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + listConfig: TAccountMetas[1]; + abWallet: TAccountMetas[2]; + systemProgram: TAccountMetas[3]; + }; + data: AddWalletToListInstructionData; +}; + +export function parseAddWalletToListInstruction< + TProgram extends string, + TAccountMetas extends readonly AccountMeta[], +>( + instruction: Instruction & + InstructionWithAccounts & + InstructionWithData +): ParsedAddWalletToListInstruction { + if (instruction.accounts.length < 4) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + listConfig: getNextAccount(), + abWallet: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getAddWalletToListInstructionDataDecoder().decode(instruction.data), + }; +} diff --git a/packages/abl/src/generated/instructions/canFreezePermissionless.ts b/packages/abl/src/generated/instructions/canFreezePermissionless.ts new file mode 100644 index 0000000..83c655f --- /dev/null +++ b/packages/abl/src/generated/instructions/canFreezePermissionless.ts @@ -0,0 +1,115 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + fixDecoderSize, + fixEncoderSize, + getBytesDecoder, + getBytesEncoder, + getStructDecoder, + getStructEncoder, + transformEncoder, + type AccountMeta, + type Address, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, + type Instruction, + type InstructionWithAccounts, + type InstructionWithData, + type ReadonlyUint8Array, +} from '@solana/kit'; +import { ABL_SRFC37_PROGRAM_ADDRESS } from '../programs'; + +export const CAN_FREEZE_PERMISSIONLESS_DISCRIMINATOR = new Uint8Array([ + 214, 141, 109, 75, 248, 1, 45, 29, +]); + +export function getCanFreezePermissionlessDiscriminatorBytes() { + return fixEncoderSize(getBytesEncoder(), 8).encode( + CAN_FREEZE_PERMISSIONLESS_DISCRIMINATOR + ); +} + +export type CanFreezePermissionlessInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TRemainingAccounts extends readonly AccountMeta[] = [], +> = Instruction & + InstructionWithData & + InstructionWithAccounts; + +export type CanFreezePermissionlessInstructionData = { + discriminator: ReadonlyUint8Array; +}; + +export type CanFreezePermissionlessInstructionDataArgs = {}; + +export function getCanFreezePermissionlessInstructionDataEncoder(): FixedSizeEncoder { + return transformEncoder( + getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), + (value) => ({ + ...value, + discriminator: CAN_FREEZE_PERMISSIONLESS_DISCRIMINATOR, + }) + ); +} + +export function getCanFreezePermissionlessInstructionDataDecoder(): FixedSizeDecoder { + return getStructDecoder([ + ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], + ]); +} + +export function getCanFreezePermissionlessInstructionDataCodec(): FixedSizeCodec< + CanFreezePermissionlessInstructionDataArgs, + CanFreezePermissionlessInstructionData +> { + return combineCodec( + getCanFreezePermissionlessInstructionDataEncoder(), + getCanFreezePermissionlessInstructionDataDecoder() + ); +} + +export type CanFreezePermissionlessInput = {}; + +export function getCanFreezePermissionlessInstruction< + TProgramAddress extends Address = typeof ABL_SRFC37_PROGRAM_ADDRESS, +>(config?: { + programAddress?: TProgramAddress; +}): CanFreezePermissionlessInstruction { + // Program address. + const programAddress = config?.programAddress ?? ABL_SRFC37_PROGRAM_ADDRESS; + + const instruction = { + programAddress, + data: getCanFreezePermissionlessInstructionDataEncoder().encode({}), + } as CanFreezePermissionlessInstruction; + + return instruction; +} + +export type ParsedCanFreezePermissionlessInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, +> = { + programAddress: Address; + data: CanFreezePermissionlessInstructionData; +}; + +export function parseCanFreezePermissionlessInstruction< + TProgram extends string, +>( + instruction: Instruction & InstructionWithData +): ParsedCanFreezePermissionlessInstruction { + return { + programAddress: instruction.programAddress, + data: getCanFreezePermissionlessInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/packages/abl/src/generated/instructions/canThawPermissionless.ts b/packages/abl/src/generated/instructions/canThawPermissionless.ts new file mode 100644 index 0000000..dd8a119 --- /dev/null +++ b/packages/abl/src/generated/instructions/canThawPermissionless.ts @@ -0,0 +1,256 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + fixDecoderSize, + fixEncoderSize, + getBytesDecoder, + getBytesEncoder, + getStructDecoder, + getStructEncoder, + transformEncoder, + type AccountMeta, + type Address, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, + type Instruction, + type InstructionWithAccounts, + type InstructionWithData, + type ReadonlyAccount, + type ReadonlyUint8Array, +} from '@solana/kit'; +import { ABL_SRFC37_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const CAN_THAW_PERMISSIONLESS_DISCRIMINATOR = new Uint8Array([ + 8, 175, 169, 129, 137, 74, 61, 241, +]); + +export function getCanThawPermissionlessDiscriminatorBytes() { + return fixEncoderSize(getBytesEncoder(), 8).encode( + CAN_THAW_PERMISSIONLESS_DISCRIMINATOR + ); +} + +export type CanThawPermissionlessInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountAuthority extends string | AccountMeta = string, + TAccountTokenAccount extends string | AccountMeta = string, + TAccountMint extends string | AccountMeta = string, + TAccountOwner extends string | AccountMeta = string, + TAccountExtraMetas extends string | AccountMeta = string, + TAccountListConfig extends string | AccountMeta = string, + TAccountAbWallet extends string | AccountMeta = string, + TRemainingAccounts extends readonly AccountMeta[] = [], +> = Instruction & + InstructionWithData & + InstructionWithAccounts< + [ + TAccountAuthority extends string + ? ReadonlyAccount + : TAccountAuthority, + TAccountTokenAccount extends string + ? ReadonlyAccount + : TAccountTokenAccount, + TAccountMint extends string + ? ReadonlyAccount + : TAccountMint, + TAccountOwner extends string + ? ReadonlyAccount + : TAccountOwner, + TAccountExtraMetas extends string + ? ReadonlyAccount + : TAccountExtraMetas, + TAccountListConfig extends string + ? ReadonlyAccount + : TAccountListConfig, + TAccountAbWallet extends string + ? ReadonlyAccount + : TAccountAbWallet, + ...TRemainingAccounts, + ] + >; + +export type CanThawPermissionlessInstructionData = { + discriminator: ReadonlyUint8Array; +}; + +export type CanThawPermissionlessInstructionDataArgs = {}; + +export function getCanThawPermissionlessInstructionDataEncoder(): FixedSizeEncoder { + return transformEncoder( + getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), + (value) => ({ + ...value, + discriminator: CAN_THAW_PERMISSIONLESS_DISCRIMINATOR, + }) + ); +} + +export function getCanThawPermissionlessInstructionDataDecoder(): FixedSizeDecoder { + return getStructDecoder([ + ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], + ]); +} + +export function getCanThawPermissionlessInstructionDataCodec(): FixedSizeCodec< + CanThawPermissionlessInstructionDataArgs, + CanThawPermissionlessInstructionData +> { + return combineCodec( + getCanThawPermissionlessInstructionDataEncoder(), + getCanThawPermissionlessInstructionDataDecoder() + ); +} + +export type CanThawPermissionlessInput< + TAccountAuthority extends string = string, + TAccountTokenAccount extends string = string, + TAccountMint extends string = string, + TAccountOwner extends string = string, + TAccountExtraMetas extends string = string, + TAccountListConfig extends string = string, + TAccountAbWallet extends string = string, +> = { + authority: Address; + tokenAccount: Address; + mint: Address; + owner: Address; + extraMetas: Address; + listConfig: Address; + abWallet: Address; +}; + +export function getCanThawPermissionlessInstruction< + TAccountAuthority extends string, + TAccountTokenAccount extends string, + TAccountMint extends string, + TAccountOwner extends string, + TAccountExtraMetas extends string, + TAccountListConfig extends string, + TAccountAbWallet extends string, + TProgramAddress extends Address = typeof ABL_SRFC37_PROGRAM_ADDRESS, +>( + input: CanThawPermissionlessInput< + TAccountAuthority, + TAccountTokenAccount, + TAccountMint, + TAccountOwner, + TAccountExtraMetas, + TAccountListConfig, + TAccountAbWallet + >, + config?: { programAddress?: TProgramAddress } +): CanThawPermissionlessInstruction< + TProgramAddress, + TAccountAuthority, + TAccountTokenAccount, + TAccountMint, + TAccountOwner, + TAccountExtraMetas, + TAccountListConfig, + TAccountAbWallet +> { + // Program address. + const programAddress = config?.programAddress ?? ABL_SRFC37_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: false }, + tokenAccount: { value: input.tokenAccount ?? null, isWritable: false }, + mint: { value: input.mint ?? null, isWritable: false }, + owner: { value: input.owner ?? null, isWritable: false }, + extraMetas: { value: input.extraMetas ?? null, isWritable: false }, + listConfig: { value: input.listConfig ?? null, isWritable: false }, + abWallet: { value: input.abWallet ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.tokenAccount), + getAccountMeta(accounts.mint), + getAccountMeta(accounts.owner), + getAccountMeta(accounts.extraMetas), + getAccountMeta(accounts.listConfig), + getAccountMeta(accounts.abWallet), + ], + programAddress, + data: getCanThawPermissionlessInstructionDataEncoder().encode({}), + } as CanThawPermissionlessInstruction< + TProgramAddress, + TAccountAuthority, + TAccountTokenAccount, + TAccountMint, + TAccountOwner, + TAccountExtraMetas, + TAccountListConfig, + TAccountAbWallet + >; + + return instruction; +} + +export type ParsedCanThawPermissionlessInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + tokenAccount: TAccountMetas[1]; + mint: TAccountMetas[2]; + owner: TAccountMetas[3]; + extraMetas: TAccountMetas[4]; + listConfig: TAccountMetas[5]; + abWallet: TAccountMetas[6]; + }; + data: CanThawPermissionlessInstructionData; +}; + +export function parseCanThawPermissionlessInstruction< + TProgram extends string, + TAccountMetas extends readonly AccountMeta[], +>( + instruction: Instruction & + InstructionWithAccounts & + InstructionWithData +): ParsedCanThawPermissionlessInstruction { + if (instruction.accounts.length < 7) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + tokenAccount: getNextAccount(), + mint: getNextAccount(), + owner: getNextAccount(), + extraMetas: getNextAccount(), + listConfig: getNextAccount(), + abWallet: getNextAccount(), + }, + data: getCanThawPermissionlessInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/packages/abl/src/generated/instructions/index.ts b/packages/abl/src/generated/instructions/index.ts new file mode 100644 index 0000000..9d793e0 --- /dev/null +++ b/packages/abl/src/generated/instructions/index.ts @@ -0,0 +1,15 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './addWalletToList'; +export * from './canFreezePermissionless'; +export * from './canThawPermissionless'; +export * from './initializeListConfig'; +export * from './removeWalletFromList'; +export * from './setExtraMetasThaw'; +export * from './setListMode'; diff --git a/packages/abl/src/generated/instructions/initializeListConfig.ts b/packages/abl/src/generated/instructions/initializeListConfig.ts new file mode 100644 index 0000000..605ebe3 --- /dev/null +++ b/packages/abl/src/generated/instructions/initializeListConfig.ts @@ -0,0 +1,239 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + fixDecoderSize, + fixEncoderSize, + getAddressDecoder, + getAddressEncoder, + getBytesDecoder, + getBytesEncoder, + getStructDecoder, + getStructEncoder, + transformEncoder, + type AccountMeta, + type AccountSignerMeta, + type Address, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, + type Instruction, + type InstructionWithAccounts, + type InstructionWithData, + type ReadonlyAccount, + type ReadonlyUint8Array, + type TransactionSigner, + type WritableAccount, + type WritableSignerAccount, +} from '@solana/kit'; +import { ABL_SRFC37_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +import { + getModeDecoder, + getModeEncoder, + type Mode, + type ModeArgs, +} from '../types'; + +export const INITIALIZE_LIST_CONFIG_DISCRIMINATOR = new Uint8Array([ + 201, 223, 17, 210, 208, 124, 101, 58, +]); + +export function getInitializeListConfigDiscriminatorBytes() { + return fixEncoderSize(getBytesEncoder(), 8).encode( + INITIALIZE_LIST_CONFIG_DISCRIMINATOR + ); +} + +export type InitializeListConfigInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountAuthority extends string | AccountMeta = string, + TAccountListConfig extends string | AccountMeta = string, + TAccountSystemProgram extends + | string + | AccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly AccountMeta[] = [], +> = Instruction & + InstructionWithData & + InstructionWithAccounts< + [ + TAccountAuthority extends string + ? WritableSignerAccount & + AccountSignerMeta + : TAccountAuthority, + TAccountListConfig extends string + ? WritableAccount + : TAccountListConfig, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type InitializeListConfigInstructionData = { + discriminator: ReadonlyUint8Array; + seed: Address; + mode: Mode; +}; + +export type InitializeListConfigInstructionDataArgs = { + seed: Address; + mode: ModeArgs; +}; + +export function getInitializeListConfigInstructionDataEncoder(): FixedSizeEncoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', fixEncoderSize(getBytesEncoder(), 8)], + ['seed', getAddressEncoder()], + ['mode', getModeEncoder()], + ]), + (value) => ({ + ...value, + discriminator: INITIALIZE_LIST_CONFIG_DISCRIMINATOR, + }) + ); +} + +export function getInitializeListConfigInstructionDataDecoder(): FixedSizeDecoder { + return getStructDecoder([ + ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], + ['seed', getAddressDecoder()], + ['mode', getModeDecoder()], + ]); +} + +export function getInitializeListConfigInstructionDataCodec(): FixedSizeCodec< + InitializeListConfigInstructionDataArgs, + InitializeListConfigInstructionData +> { + return combineCodec( + getInitializeListConfigInstructionDataEncoder(), + getInitializeListConfigInstructionDataDecoder() + ); +} + +export type InitializeListConfigInput< + TAccountAuthority extends string = string, + TAccountListConfig extends string = string, + TAccountSystemProgram extends string = string, +> = { + authority: TransactionSigner; + listConfig: Address; + systemProgram?: Address; + seed: InitializeListConfigInstructionDataArgs['seed']; + mode: InitializeListConfigInstructionDataArgs['mode']; +}; + +export function getInitializeListConfigInstruction< + TAccountAuthority extends string, + TAccountListConfig extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof ABL_SRFC37_PROGRAM_ADDRESS, +>( + input: InitializeListConfigInput< + TAccountAuthority, + TAccountListConfig, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): InitializeListConfigInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountSystemProgram +> { + // Program address. + const programAddress = config?.programAddress ?? ABL_SRFC37_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: true }, + listConfig: { value: input.listConfig ?? null, isWritable: true }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Resolve default values. + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.listConfig), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getInitializeListConfigInstructionDataEncoder().encode( + args as InitializeListConfigInstructionDataArgs + ), + } as InitializeListConfigInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedInitializeListConfigInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + listConfig: TAccountMetas[1]; + systemProgram: TAccountMetas[2]; + }; + data: InitializeListConfigInstructionData; +}; + +export function parseInitializeListConfigInstruction< + TProgram extends string, + TAccountMetas extends readonly AccountMeta[], +>( + instruction: Instruction & + InstructionWithAccounts & + InstructionWithData +): ParsedInitializeListConfigInstruction { + if (instruction.accounts.length < 3) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + listConfig: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getInitializeListConfigInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/packages/abl/src/generated/instructions/removeWalletFromList.ts b/packages/abl/src/generated/instructions/removeWalletFromList.ts new file mode 100644 index 0000000..e6011c7 --- /dev/null +++ b/packages/abl/src/generated/instructions/removeWalletFromList.ts @@ -0,0 +1,227 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + fixDecoderSize, + fixEncoderSize, + getBytesDecoder, + getBytesEncoder, + getStructDecoder, + getStructEncoder, + transformEncoder, + type AccountMeta, + type AccountSignerMeta, + type Address, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, + type Instruction, + type InstructionWithAccounts, + type InstructionWithData, + type ReadonlyAccount, + type ReadonlyUint8Array, + type TransactionSigner, + type WritableAccount, + type WritableSignerAccount, +} from '@solana/kit'; +import { ABL_SRFC37_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const REMOVE_WALLET_FROM_LIST_DISCRIMINATOR = new Uint8Array([ + 185, 14, 13, 222, 207, 118, 221, 146, +]); + +export function getRemoveWalletFromListDiscriminatorBytes() { + return fixEncoderSize(getBytesEncoder(), 8).encode( + REMOVE_WALLET_FROM_LIST_DISCRIMINATOR + ); +} + +export type RemoveWalletFromListInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountAuthority extends string | AccountMeta = string, + TAccountListConfig extends string | AccountMeta = string, + TAccountAbWallet extends string | AccountMeta = string, + TAccountSystemProgram extends + | string + | AccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly AccountMeta[] = [], +> = Instruction & + InstructionWithData & + InstructionWithAccounts< + [ + TAccountAuthority extends string + ? WritableSignerAccount & + AccountSignerMeta + : TAccountAuthority, + TAccountListConfig extends string + ? ReadonlyAccount + : TAccountListConfig, + TAccountAbWallet extends string + ? WritableAccount + : TAccountAbWallet, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type RemoveWalletFromListInstructionData = { + discriminator: ReadonlyUint8Array; +}; + +export type RemoveWalletFromListInstructionDataArgs = {}; + +export function getRemoveWalletFromListInstructionDataEncoder(): FixedSizeEncoder { + return transformEncoder( + getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), + (value) => ({ + ...value, + discriminator: REMOVE_WALLET_FROM_LIST_DISCRIMINATOR, + }) + ); +} + +export function getRemoveWalletFromListInstructionDataDecoder(): FixedSizeDecoder { + return getStructDecoder([ + ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], + ]); +} + +export function getRemoveWalletFromListInstructionDataCodec(): FixedSizeCodec< + RemoveWalletFromListInstructionDataArgs, + RemoveWalletFromListInstructionData +> { + return combineCodec( + getRemoveWalletFromListInstructionDataEncoder(), + getRemoveWalletFromListInstructionDataDecoder() + ); +} + +export type RemoveWalletFromListInput< + TAccountAuthority extends string = string, + TAccountListConfig extends string = string, + TAccountAbWallet extends string = string, + TAccountSystemProgram extends string = string, +> = { + authority: TransactionSigner; + listConfig: Address; + abWallet: Address; + systemProgram?: Address; +}; + +export function getRemoveWalletFromListInstruction< + TAccountAuthority extends string, + TAccountListConfig extends string, + TAccountAbWallet extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof ABL_SRFC37_PROGRAM_ADDRESS, +>( + input: RemoveWalletFromListInput< + TAccountAuthority, + TAccountListConfig, + TAccountAbWallet, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): RemoveWalletFromListInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountAbWallet, + TAccountSystemProgram +> { + // Program address. + const programAddress = config?.programAddress ?? ABL_SRFC37_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: true }, + listConfig: { value: input.listConfig ?? null, isWritable: false }, + abWallet: { value: input.abWallet ?? null, isWritable: true }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Resolve default values. + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.listConfig), + getAccountMeta(accounts.abWallet), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getRemoveWalletFromListInstructionDataEncoder().encode({}), + } as RemoveWalletFromListInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountAbWallet, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedRemoveWalletFromListInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + listConfig: TAccountMetas[1]; + abWallet: TAccountMetas[2]; + systemProgram: TAccountMetas[3]; + }; + data: RemoveWalletFromListInstructionData; +}; + +export function parseRemoveWalletFromListInstruction< + TProgram extends string, + TAccountMetas extends readonly AccountMeta[], +>( + instruction: Instruction & + InstructionWithAccounts & + InstructionWithData +): ParsedRemoveWalletFromListInstruction { + if (instruction.accounts.length < 4) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + listConfig: getNextAccount(), + abWallet: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getRemoveWalletFromListInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/packages/abl/src/generated/instructions/setExtraMetasThaw.ts b/packages/abl/src/generated/instructions/setExtraMetasThaw.ts new file mode 100644 index 0000000..8cdde8e --- /dev/null +++ b/packages/abl/src/generated/instructions/setExtraMetasThaw.ts @@ -0,0 +1,381 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + fixDecoderSize, + fixEncoderSize, + getAddressEncoder, + getBytesDecoder, + getBytesEncoder, + getProgramDerivedAddress, + getStructDecoder, + getStructEncoder, + transformEncoder, + type AccountMeta, + type AccountSignerMeta, + type Address, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, + type Instruction, + type InstructionWithAccounts, + type InstructionWithData, + type ReadonlyAccount, + type ReadonlyUint8Array, + type TransactionSigner, + type WritableAccount, + type WritableSignerAccount, +} from '@solana/kit'; +import { ABL_SRFC37_PROGRAM_ADDRESS } from '../programs'; +import { + expectAddress, + getAccountMetaFactory, + type ResolvedAccount, +} from '../shared'; + +export const SET_EXTRA_METAS_THAW_DISCRIMINATOR = new Uint8Array([ + 6, 94, 201, 255, 159, 241, 169, 164, +]); + +export function getSetExtraMetasThawDiscriminatorBytes() { + return fixEncoderSize(getBytesEncoder(), 8).encode( + SET_EXTRA_METAS_THAW_DISCRIMINATOR + ); +} + +export type SetExtraMetasThawInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountAuthority extends string | AccountMeta = string, + TAccountListConfig extends string | AccountMeta = string, + TAccountEbaltsMintConfig extends string | AccountMeta = string, + TAccountMint extends string | AccountMeta = string, + TAccountExtraMetasThaw extends string | AccountMeta = string, + TAccountSystemProgram extends + | string + | AccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly AccountMeta[] = [], +> = Instruction & + InstructionWithData & + InstructionWithAccounts< + [ + TAccountAuthority extends string + ? WritableSignerAccount & + AccountSignerMeta + : TAccountAuthority, + TAccountListConfig extends string + ? ReadonlyAccount + : TAccountListConfig, + TAccountEbaltsMintConfig extends string + ? ReadonlyAccount + : TAccountEbaltsMintConfig, + TAccountMint extends string + ? ReadonlyAccount + : TAccountMint, + TAccountExtraMetasThaw extends string + ? WritableAccount + : TAccountExtraMetasThaw, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type SetExtraMetasThawInstructionData = { + discriminator: ReadonlyUint8Array; +}; + +export type SetExtraMetasThawInstructionDataArgs = {}; + +export function getSetExtraMetasThawInstructionDataEncoder(): FixedSizeEncoder { + return transformEncoder( + getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), + (value) => ({ ...value, discriminator: SET_EXTRA_METAS_THAW_DISCRIMINATOR }) + ); +} + +export function getSetExtraMetasThawInstructionDataDecoder(): FixedSizeDecoder { + return getStructDecoder([ + ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], + ]); +} + +export function getSetExtraMetasThawInstructionDataCodec(): FixedSizeCodec< + SetExtraMetasThawInstructionDataArgs, + SetExtraMetasThawInstructionData +> { + return combineCodec( + getSetExtraMetasThawInstructionDataEncoder(), + getSetExtraMetasThawInstructionDataDecoder() + ); +} + +export type SetExtraMetasThawAsyncInput< + TAccountAuthority extends string = string, + TAccountListConfig extends string = string, + TAccountEbaltsMintConfig extends string = string, + TAccountMint extends string = string, + TAccountExtraMetasThaw extends string = string, + TAccountSystemProgram extends string = string, +> = { + authority: TransactionSigner; + listConfig: Address; + ebaltsMintConfig?: Address; + mint: Address; + extraMetasThaw?: Address; + systemProgram?: Address; +}; + +export async function getSetExtraMetasThawInstructionAsync< + TAccountAuthority extends string, + TAccountListConfig extends string, + TAccountEbaltsMintConfig extends string, + TAccountMint extends string, + TAccountExtraMetasThaw extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof ABL_SRFC37_PROGRAM_ADDRESS, +>( + input: SetExtraMetasThawAsyncInput< + TAccountAuthority, + TAccountListConfig, + TAccountEbaltsMintConfig, + TAccountMint, + TAccountExtraMetasThaw, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): Promise< + SetExtraMetasThawInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountEbaltsMintConfig, + TAccountMint, + TAccountExtraMetasThaw, + TAccountSystemProgram + > +> { + // Program address. + const programAddress = config?.programAddress ?? ABL_SRFC37_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: true }, + listConfig: { value: input.listConfig ?? null, isWritable: false }, + ebaltsMintConfig: { + value: input.ebaltsMintConfig ?? null, + isWritable: false, + }, + mint: { value: input.mint ?? null, isWritable: false }, + extraMetasThaw: { value: input.extraMetasThaw ?? null, isWritable: true }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Resolve default values. + if (!accounts.ebaltsMintConfig.value) { + accounts.ebaltsMintConfig.value = await getProgramDerivedAddress({ + programAddress: + 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, + seeds: [ + getBytesEncoder().encode( + new Uint8Array([77, 73, 78, 84, 95, 67, 79, 78, 70, 73, 71]) + ), + getAddressEncoder().encode(expectAddress(accounts.mint.value)), + ], + }); + } + if (!accounts.extraMetasThaw.value) { + accounts.extraMetasThaw.value = await getProgramDerivedAddress({ + programAddress, + seeds: [ + getBytesEncoder().encode( + new Uint8Array([ + 116, 104, 97, 119, 95, 101, 120, 116, 114, 97, 95, 97, 99, 99, 111, + 117, 110, 116, 95, 109, 101, 116, 97, 115, + ]) + ), + getAddressEncoder().encode(expectAddress(accounts.mint.value)), + ], + }); + } + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.listConfig), + getAccountMeta(accounts.ebaltsMintConfig), + getAccountMeta(accounts.mint), + getAccountMeta(accounts.extraMetasThaw), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getSetExtraMetasThawInstructionDataEncoder().encode({}), + } as SetExtraMetasThawInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountEbaltsMintConfig, + TAccountMint, + TAccountExtraMetasThaw, + TAccountSystemProgram + >; + + return instruction; +} + +export type SetExtraMetasThawInput< + TAccountAuthority extends string = string, + TAccountListConfig extends string = string, + TAccountEbaltsMintConfig extends string = string, + TAccountMint extends string = string, + TAccountExtraMetasThaw extends string = string, + TAccountSystemProgram extends string = string, +> = { + authority: TransactionSigner; + listConfig: Address; + ebaltsMintConfig: Address; + mint: Address; + extraMetasThaw: Address; + systemProgram?: Address; +}; + +export function getSetExtraMetasThawInstruction< + TAccountAuthority extends string, + TAccountListConfig extends string, + TAccountEbaltsMintConfig extends string, + TAccountMint extends string, + TAccountExtraMetasThaw extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof ABL_SRFC37_PROGRAM_ADDRESS, +>( + input: SetExtraMetasThawInput< + TAccountAuthority, + TAccountListConfig, + TAccountEbaltsMintConfig, + TAccountMint, + TAccountExtraMetasThaw, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): SetExtraMetasThawInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountEbaltsMintConfig, + TAccountMint, + TAccountExtraMetasThaw, + TAccountSystemProgram +> { + // Program address. + const programAddress = config?.programAddress ?? ABL_SRFC37_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: true }, + listConfig: { value: input.listConfig ?? null, isWritable: false }, + ebaltsMintConfig: { + value: input.ebaltsMintConfig ?? null, + isWritable: false, + }, + mint: { value: input.mint ?? null, isWritable: false }, + extraMetasThaw: { value: input.extraMetasThaw ?? null, isWritable: true }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Resolve default values. + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.listConfig), + getAccountMeta(accounts.ebaltsMintConfig), + getAccountMeta(accounts.mint), + getAccountMeta(accounts.extraMetasThaw), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getSetExtraMetasThawInstructionDataEncoder().encode({}), + } as SetExtraMetasThawInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig, + TAccountEbaltsMintConfig, + TAccountMint, + TAccountExtraMetasThaw, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedSetExtraMetasThawInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + listConfig: TAccountMetas[1]; + ebaltsMintConfig: TAccountMetas[2]; + mint: TAccountMetas[3]; + extraMetasThaw: TAccountMetas[4]; + systemProgram: TAccountMetas[5]; + }; + data: SetExtraMetasThawInstructionData; +}; + +export function parseSetExtraMetasThawInstruction< + TProgram extends string, + TAccountMetas extends readonly AccountMeta[], +>( + instruction: Instruction & + InstructionWithAccounts & + InstructionWithData +): ParsedSetExtraMetasThawInstruction { + if (instruction.accounts.length < 6) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + listConfig: getNextAccount(), + ebaltsMintConfig: getNextAccount(), + mint: getNextAccount(), + extraMetasThaw: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getSetExtraMetasThawInstructionDataDecoder().decode(instruction.data), + }; +} diff --git a/packages/abl/src/generated/instructions/setListMode.ts b/packages/abl/src/generated/instructions/setListMode.ts new file mode 100644 index 0000000..2445a64 --- /dev/null +++ b/packages/abl/src/generated/instructions/setListMode.ts @@ -0,0 +1,199 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + fixDecoderSize, + fixEncoderSize, + getBytesDecoder, + getBytesEncoder, + getStructDecoder, + getStructEncoder, + transformEncoder, + type AccountMeta, + type AccountSignerMeta, + type Address, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, + type Instruction, + type InstructionWithAccounts, + type InstructionWithData, + type ReadonlyAccount, + type ReadonlyUint8Array, + type TransactionSigner, + type WritableSignerAccount, +} from '@solana/kit'; +import { ABL_SRFC37_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +import { + getModeDecoder, + getModeEncoder, + type Mode, + type ModeArgs, +} from '../types'; + +export const SET_LIST_MODE_DISCRIMINATOR = new Uint8Array([ + 174, 19, 169, 240, 19, 9, 146, 12, +]); + +export function getSetListModeDiscriminatorBytes() { + return fixEncoderSize(getBytesEncoder(), 8).encode( + SET_LIST_MODE_DISCRIMINATOR + ); +} + +export type SetListModeInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountAuthority extends string | AccountMeta = string, + TAccountListConfig extends string | AccountMeta = string, + TRemainingAccounts extends readonly AccountMeta[] = [], +> = Instruction & + InstructionWithData & + InstructionWithAccounts< + [ + TAccountAuthority extends string + ? WritableSignerAccount & + AccountSignerMeta + : TAccountAuthority, + TAccountListConfig extends string + ? ReadonlyAccount + : TAccountListConfig, + ...TRemainingAccounts, + ] + >; + +export type SetListModeInstructionData = { + discriminator: ReadonlyUint8Array; + mode: Mode; +}; + +export type SetListModeInstructionDataArgs = { mode: ModeArgs }; + +export function getSetListModeInstructionDataEncoder(): FixedSizeEncoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', fixEncoderSize(getBytesEncoder(), 8)], + ['mode', getModeEncoder()], + ]), + (value) => ({ ...value, discriminator: SET_LIST_MODE_DISCRIMINATOR }) + ); +} + +export function getSetListModeInstructionDataDecoder(): FixedSizeDecoder { + return getStructDecoder([ + ['discriminator', fixDecoderSize(getBytesDecoder(), 8)], + ['mode', getModeDecoder()], + ]); +} + +export function getSetListModeInstructionDataCodec(): FixedSizeCodec< + SetListModeInstructionDataArgs, + SetListModeInstructionData +> { + return combineCodec( + getSetListModeInstructionDataEncoder(), + getSetListModeInstructionDataDecoder() + ); +} + +export type SetListModeInput< + TAccountAuthority extends string = string, + TAccountListConfig extends string = string, +> = { + authority: TransactionSigner; + listConfig: Address; + mode: SetListModeInstructionDataArgs['mode']; +}; + +export function getSetListModeInstruction< + TAccountAuthority extends string, + TAccountListConfig extends string, + TProgramAddress extends Address = typeof ABL_SRFC37_PROGRAM_ADDRESS, +>( + input: SetListModeInput, + config?: { programAddress?: TProgramAddress } +): SetListModeInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig +> { + // Program address. + const programAddress = config?.programAddress ?? ABL_SRFC37_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: true }, + listConfig: { value: input.listConfig ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.listConfig), + ], + programAddress, + data: getSetListModeInstructionDataEncoder().encode( + args as SetListModeInstructionDataArgs + ), + } as SetListModeInstruction< + TProgramAddress, + TAccountAuthority, + TAccountListConfig + >; + + return instruction; +} + +export type ParsedSetListModeInstruction< + TProgram extends string = typeof ABL_SRFC37_PROGRAM_ADDRESS, + TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + listConfig: TAccountMetas[1]; + }; + data: SetListModeInstructionData; +}; + +export function parseSetListModeInstruction< + TProgram extends string, + TAccountMetas extends readonly AccountMeta[], +>( + instruction: Instruction & + InstructionWithAccounts & + InstructionWithData +): ParsedSetListModeInstruction { + if (instruction.accounts.length < 2) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + listConfig: getNextAccount(), + }, + data: getSetListModeInstructionDataDecoder().decode(instruction.data), + }; +} diff --git a/packages/abl/src/generated/programs/ablSrfc37.ts b/packages/abl/src/generated/programs/ablSrfc37.ts new file mode 100644 index 0000000..aad991d --- /dev/null +++ b/packages/abl/src/generated/programs/ablSrfc37.ts @@ -0,0 +1,184 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + containsBytes, + fixEncoderSize, + getBytesEncoder, + type Address, + type ReadonlyUint8Array, +} from '@solana/kit'; +import { + type ParsedAddWalletToListInstruction, + type ParsedCanFreezePermissionlessInstruction, + type ParsedCanThawPermissionlessInstruction, + type ParsedInitializeListConfigInstruction, + type ParsedRemoveWalletFromListInstruction, + type ParsedSetExtraMetasThawInstruction, + type ParsedSetListModeInstruction, +} from '../instructions'; + +export const ABL_SRFC37_PROGRAM_ADDRESS = + '8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N' as Address<'8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N'>; + +export enum AblSrfc37Account { + ABWallet, + ListConfig, +} + +export function identifyAblSrfc37Account( + account: { data: ReadonlyUint8Array } | ReadonlyUint8Array +): AblSrfc37Account { + const data = 'data' in account ? account.data : account; + if ( + containsBytes( + data, + fixEncoderSize(getBytesEncoder(), 8).encode( + new Uint8Array([111, 162, 31, 45, 79, 239, 198, 72]) + ), + 0 + ) + ) { + return AblSrfc37Account.ABWallet; + } + if ( + containsBytes( + data, + fixEncoderSize(getBytesEncoder(), 8).encode( + new Uint8Array([9, 220, 3, 74, 122, 218, 71, 204]) + ), + 0 + ) + ) { + return AblSrfc37Account.ListConfig; + } + throw new Error( + 'The provided account could not be identified as a ablSrfc37 account.' + ); +} + +export enum AblSrfc37Instruction { + AddWalletToList, + CanFreezePermissionless, + CanThawPermissionless, + InitializeListConfig, + RemoveWalletFromList, + SetExtraMetasThaw, + SetListMode, +} + +export function identifyAblSrfc37Instruction( + instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array +): AblSrfc37Instruction { + const data = 'data' in instruction ? instruction.data : instruction; + if ( + containsBytes( + data, + fixEncoderSize(getBytesEncoder(), 8).encode( + new Uint8Array([249, 25, 0, 35, 88, 124, 60, 201]) + ), + 0 + ) + ) { + return AblSrfc37Instruction.AddWalletToList; + } + if ( + containsBytes( + data, + fixEncoderSize(getBytesEncoder(), 8).encode( + new Uint8Array([214, 141, 109, 75, 248, 1, 45, 29]) + ), + 0 + ) + ) { + return AblSrfc37Instruction.CanFreezePermissionless; + } + if ( + containsBytes( + data, + fixEncoderSize(getBytesEncoder(), 8).encode( + new Uint8Array([8, 175, 169, 129, 137, 74, 61, 241]) + ), + 0 + ) + ) { + return AblSrfc37Instruction.CanThawPermissionless; + } + if ( + containsBytes( + data, + fixEncoderSize(getBytesEncoder(), 8).encode( + new Uint8Array([201, 223, 17, 210, 208, 124, 101, 58]) + ), + 0 + ) + ) { + return AblSrfc37Instruction.InitializeListConfig; + } + if ( + containsBytes( + data, + fixEncoderSize(getBytesEncoder(), 8).encode( + new Uint8Array([185, 14, 13, 222, 207, 118, 221, 146]) + ), + 0 + ) + ) { + return AblSrfc37Instruction.RemoveWalletFromList; + } + if ( + containsBytes( + data, + fixEncoderSize(getBytesEncoder(), 8).encode( + new Uint8Array([6, 94, 201, 255, 159, 241, 169, 164]) + ), + 0 + ) + ) { + return AblSrfc37Instruction.SetExtraMetasThaw; + } + if ( + containsBytes( + data, + fixEncoderSize(getBytesEncoder(), 8).encode( + new Uint8Array([174, 19, 169, 240, 19, 9, 146, 12]) + ), + 0 + ) + ) { + return AblSrfc37Instruction.SetListMode; + } + throw new Error( + 'The provided instruction could not be identified as a ablSrfc37 instruction.' + ); +} + +export type ParsedAblSrfc37Instruction< + TProgram extends string = '8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N', +> = + | ({ + instructionType: AblSrfc37Instruction.AddWalletToList; + } & ParsedAddWalletToListInstruction) + | ({ + instructionType: AblSrfc37Instruction.CanFreezePermissionless; + } & ParsedCanFreezePermissionlessInstruction) + | ({ + instructionType: AblSrfc37Instruction.CanThawPermissionless; + } & ParsedCanThawPermissionlessInstruction) + | ({ + instructionType: AblSrfc37Instruction.InitializeListConfig; + } & ParsedInitializeListConfigInstruction) + | ({ + instructionType: AblSrfc37Instruction.RemoveWalletFromList; + } & ParsedRemoveWalletFromListInstruction) + | ({ + instructionType: AblSrfc37Instruction.SetExtraMetasThaw; + } & ParsedSetExtraMetasThawInstruction) + | ({ + instructionType: AblSrfc37Instruction.SetListMode; + } & ParsedSetListModeInstruction); diff --git a/packages/abl/src/generated/programs/index.ts b/packages/abl/src/generated/programs/index.ts new file mode 100644 index 0000000..e8d71dd --- /dev/null +++ b/packages/abl/src/generated/programs/index.ts @@ -0,0 +1,9 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './ablSrfc37'; diff --git a/packages/abl/src/generated/shared/index.ts b/packages/abl/src/generated/shared/index.ts new file mode 100644 index 0000000..7ebc265 --- /dev/null +++ b/packages/abl/src/generated/shared/index.ts @@ -0,0 +1,164 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + AccountRole, + isProgramDerivedAddress, + isTransactionSigner as kitIsTransactionSigner, + type AccountMeta, + type AccountSignerMeta, + type Address, + type ProgramDerivedAddress, + type TransactionSigner, + upgradeRoleToSigner, +} from '@solana/kit'; + +/** + * Asserts that the given value is not null or undefined. + * @internal + */ +export function expectSome(value: T | null | undefined): T { + if (value == null) { + throw new Error('Expected a value but received null or undefined.'); + } + return value; +} + +/** + * Asserts that the given value is a PublicKey. + * @internal + */ +export function expectAddress( + value: + | Address + | ProgramDerivedAddress + | TransactionSigner + | null + | undefined +): Address { + if (!value) { + throw new Error('Expected a Address.'); + } + if (typeof value === 'object' && 'address' in value) { + return value.address; + } + if (Array.isArray(value)) { + return value[0]; + } + return value as Address; +} + +/** + * Asserts that the given value is a PDA. + * @internal + */ +export function expectProgramDerivedAddress( + value: + | Address + | ProgramDerivedAddress + | TransactionSigner + | null + | undefined +): ProgramDerivedAddress { + if (!value || !Array.isArray(value) || !isProgramDerivedAddress(value)) { + throw new Error('Expected a ProgramDerivedAddress.'); + } + return value; +} + +/** + * Asserts that the given value is a TransactionSigner. + * @internal + */ +export function expectTransactionSigner( + value: + | Address + | ProgramDerivedAddress + | TransactionSigner + | null + | undefined +): TransactionSigner { + if (!value || !isTransactionSigner(value)) { + throw new Error('Expected a TransactionSigner.'); + } + return value; +} + +/** + * Defines an instruction account to resolve. + * @internal + */ +export type ResolvedAccount< + T extends string = string, + U extends + | Address + | ProgramDerivedAddress + | TransactionSigner + | null = + | Address + | ProgramDerivedAddress + | TransactionSigner + | null, +> = { + isWritable: boolean; + value: U; +}; + +/** + * Defines an instruction that stores additional bytes on-chain. + * @internal + */ +export type InstructionWithByteDelta = { + byteDelta: number; +}; + +/** + * Get account metas and signers from resolved accounts. + * @internal + */ +export function getAccountMetaFactory( + programAddress: Address, + optionalAccountStrategy: 'omitted' | 'programId' +) { + return ( + account: ResolvedAccount + ): AccountMeta | AccountSignerMeta | undefined => { + if (!account.value) { + if (optionalAccountStrategy === 'omitted') return; + return Object.freeze({ + address: programAddress, + role: AccountRole.READONLY, + }); + } + + const writableRole = account.isWritable + ? AccountRole.WRITABLE + : AccountRole.READONLY; + return Object.freeze({ + address: expectAddress(account.value), + role: isTransactionSigner(account.value) + ? upgradeRoleToSigner(writableRole) + : writableRole, + ...(isTransactionSigner(account.value) ? { signer: account.value } : {}), + }); + }; +} + +export function isTransactionSigner( + value: + | Address + | ProgramDerivedAddress + | TransactionSigner +): value is TransactionSigner { + return ( + !!value && + typeof value === 'object' && + 'address' in value && + kitIsTransactionSigner(value) + ); +} diff --git a/packages/abl/src/generated/types/index.ts b/packages/abl/src/generated/types/index.ts new file mode 100644 index 0000000..7b9ce66 --- /dev/null +++ b/packages/abl/src/generated/types/index.ts @@ -0,0 +1,9 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './mode'; diff --git a/packages/abl/src/generated/types/mode.ts b/packages/abl/src/generated/types/mode.ts new file mode 100644 index 0000000..c227db9 --- /dev/null +++ b/packages/abl/src/generated/types/mode.ts @@ -0,0 +1,36 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getEnumDecoder, + getEnumEncoder, + type FixedSizeCodec, + type FixedSizeDecoder, + type FixedSizeEncoder, +} from '@solana/kit'; + +export enum Mode { + Allow, + AllowWithPermissionlessEOAs, + Block, +} + +export type ModeArgs = Mode; + +export function getModeEncoder(): FixedSizeEncoder { + return getEnumEncoder(Mode); +} + +export function getModeDecoder(): FixedSizeDecoder { + return getEnumDecoder(Mode); +} + +export function getModeCodec(): FixedSizeCodec { + return combineCodec(getModeEncoder(), getModeDecoder()); +} diff --git a/packages/abl/src/index.ts b/packages/abl/src/index.ts new file mode 100644 index 0000000..7c8ec4b --- /dev/null +++ b/packages/abl/src/index.ts @@ -0,0 +1,53 @@ + +import { + getAddressEncoder, + getProgramDerivedAddress, + getUtf8Encoder, + type Address, + type ProgramDerivedAddress, +} from '@solana/kit'; + +export type ListConfigSeeds = { + authority: Address; + seed: Address; +}; + +export async function findListConfigPda( + seeds: ListConfigSeeds, + config: { programAddress?: Address | undefined } = {} +): Promise { + const { + programAddress = 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, + } = config; + return await getProgramDerivedAddress({ + programAddress, + seeds: [ + getUtf8Encoder().encode('list_config'), + getAddressEncoder().encode(seeds.authority), + getAddressEncoder().encode(seeds.seed), + ], + }); +} + +export type ABWalletSeeds = { + wallet: Address; + list: Address; +}; + +export async function findABWalletPda( + seeds: ABWalletSeeds, + config: { programAddress?: Address | undefined } = {} +): Promise { + const { + programAddress = 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, + } = config; + return await getProgramDerivedAddress({ + programAddress, + seeds: [ + getAddressEncoder().encode(seeds.list), + getAddressEncoder().encode(seeds.wallet), + ], + }); +} + +export * from './generated'; \ No newline at end of file diff --git a/packages/abl/tsconfig.json b/packages/abl/tsconfig.json new file mode 100644 index 0000000..01db065 --- /dev/null +++ b/packages/abl/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"], + "types": ["jest", "node"] +} diff --git a/packages/cli/package.json b/packages/cli/package.json index a1db9d5..28e6134 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -22,6 +22,9 @@ }, "dependencies": { "@mosaic/sdk": "workspace:*", + "@mosaic/tlv-account-resolution": "workspace:*", + "@mosaic/ebalts": "workspace:*", + "@mosaic/abl": "workspace:*", "commander": "^12.0.0", "chalk": "^5.3.0", "ora": "^8.0.1", diff --git a/packages/cli/src/commands/abl/abl.ts b/packages/cli/src/commands/abl/abl.ts new file mode 100644 index 0000000..6e7cf88 --- /dev/null +++ b/packages/cli/src/commands/abl/abl.ts @@ -0,0 +1,7 @@ +import { Command } from 'commander'; +import { createList } from './createList.js'; +import { setExtraMetas } from './setExtraMetas.js'; + +export const ablCommand = new Command('abl') + .addCommand(createList) + .addCommand(setExtraMetas); \ No newline at end of file diff --git a/packages/cli/src/commands/abl/createList.ts b/packages/cli/src/commands/abl/createList.ts new file mode 100644 index 0000000..60febbd --- /dev/null +++ b/packages/cli/src/commands/abl/createList.ts @@ -0,0 +1,82 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +import ora from 'ora'; +import { createArcadeTokenInitTransaction, getCreateListTransaction } from '@mosaic/sdk'; +import { createSolanaClient } from '../../utils/rpc.js'; +import { loadKeypair } from '../../utils/solana.js'; +import { + compressTransactionMessageUsingAddressLookupTables, + createTransaction, + generateKeyPairSigner, + signTransactionMessageWithSigners, + SolanaError, + type Address, +} from 'gill'; + +interface CreateConfigOptions { + mint: string; + gatingProgram: string; + rpcUrl?: string; + keypair?: string; +} + +export const createList = new Command('create-list') + .description('Create a new list for an existing mint') + .action(async (options: CreateConfigOptions, command) => { + const spinner = ora('Creating ebalts config...').start(); + + try { + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; + const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); + const kp = await loadKeypair(options.keypair); + + console.log(options); + console.log(parentOpts); + + const {transaction, listConfig} = await getCreateListTransaction({ + rpc, + payer: kp, + authority: kp, + }); + + + spinner.text = 'Signing transaction...'; + + // Sign the transaction + const signedTransaction = + await signTransactionMessageWithSigners(transaction); + + spinner.text = 'Sending transaction...'; + + // Send and confirm transaction + const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + + spinner.succeed('Ebalts config created successfully!'); + + // Display results + console.log(chalk.green('✅ ABL list created successfully!')); + console.log(chalk.cyan('📋 Details:')); + console.log(` ${chalk.bold('List Config:')} ${listConfig}`); + console.log(` ${chalk.bold('Transaction:')} ${signature}`); + } + catch (error) { + spinner.fail('Failed to create ebalts config'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + console.error( + chalk.red('❌ Error:'), + error + ); + console.error( + chalk.red('❌ Error:'), + error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); \ No newline at end of file diff --git a/packages/cli/src/commands/abl/setExtraMetas.ts b/packages/cli/src/commands/abl/setExtraMetas.ts new file mode 100644 index 0000000..80bb2a0 --- /dev/null +++ b/packages/cli/src/commands/abl/setExtraMetas.ts @@ -0,0 +1,83 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +import ora from 'ora'; +import { createArcadeTokenInitTransaction, getSetExtraMetasTransaction } from '@mosaic/sdk'; +import { createSolanaClient } from '../../utils/rpc.js'; +import { loadKeypair } from '../../utils/solana.js'; +import { + compressTransactionMessageUsingAddressLookupTables, + createTransaction, + generateKeyPairSigner, + signTransactionMessageWithSigners, + SolanaError, + type Address, +} from 'gill'; + +interface CreateConfigOptions { + mint: string; + list: string; + rpcUrl?: string; + keypair?: string; +} + +export const setExtraMetas = new Command('set-extra-metas') + .description('Set extra metas for an existing list') + .requiredOption('-m, --mint ', 'Mint address') + .requiredOption('-l, --list ', 'List address') + .action(async (options: CreateConfigOptions, command) => { + const spinner = ora('Setting extra metas...').start(); + + try { + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; + const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); + const kp = await loadKeypair(keypairPath); + + console.log(options); + console.log(parentOpts); + + const transaction = await getSetExtraMetasTransaction({ + rpc, + payer: kp, + authority: kp, + mint: options.mint as Address, + list: options.list as Address, + }); + + + spinner.text = 'Signing transaction...'; + + // Sign the transaction + const signedTransaction = + await signTransactionMessageWithSigners(transaction); + + spinner.text = 'Sending transaction...'; + + // Send and confirm transaction + const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + + spinner.succeed('Extra metas set successfully!'); + + // Display results + console.log(chalk.green('✅ Extra metas set successfully!')); + } + catch (error) { + spinner.fail('Failed to create ebalts config'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + console.error( + chalk.red('❌ Error:'), + error + ); + console.error( + chalk.red('❌ Error:'), + error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); \ No newline at end of file diff --git a/packages/cli/src/commands/abl/utils.ts b/packages/cli/src/commands/abl/utils.ts new file mode 100644 index 0000000..be68de0 --- /dev/null +++ b/packages/cli/src/commands/abl/utils.ts @@ -0,0 +1,4 @@ +import type { Address } from "gill"; + + +export const ABL_PROGRAM_ID = '8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N' as Address; \ No newline at end of file diff --git a/packages/cli/src/commands/create/arcade-token.ts b/packages/cli/src/commands/create/arcade-token.ts index 3c06ac8..f9d5235 100644 --- a/packages/cli/src/commands/create/arcade-token.ts +++ b/packages/cli/src/commands/create/arcade-token.ts @@ -60,7 +60,7 @@ export const createArcadeTokenCommand = new Command('arcade-token') try { // Get global options from parent command - const parentOpts = command.parent?.opts() || {}; + const parentOpts = command.parent?.parent?.opts() || {}; const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; const keypairPath = options.keypair || parentOpts.keypair; @@ -123,7 +123,7 @@ export const createArcadeTokenCommand = new Command('arcade-token') spinner.text = 'Sending transaction...'; // Send and confirm transaction - const signature = await sendAndConfirmTransaction(signedTransaction); + const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); spinner.succeed('Arcade token created successfully!'); diff --git a/packages/cli/src/commands/ebalts/createConfig.ts b/packages/cli/src/commands/ebalts/createConfig.ts new file mode 100644 index 0000000..86d17c9 --- /dev/null +++ b/packages/cli/src/commands/ebalts/createConfig.ts @@ -0,0 +1,94 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +import ora from 'ora'; +import { createArcadeTokenInitTransaction, getCreateConfigTransaction } from '@mosaic/sdk'; +import { createSolanaClient } from '../../utils/rpc.js'; +import { loadKeypair } from '../../utils/solana.js'; +import { + compressTransactionMessageUsingAddressLookupTables, + createTransaction, + generateKeyPairSigner, + signTransactionMessageWithSigners, + SolanaError, + type Address, +} from 'gill'; +import { findMintConfigPda, getCreateConfigInstruction } from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from './util.js'; + +interface CreateConfigOptions { + mint: string; + gatingProgram: string; + rpcUrl?: string; + keypair?: string; +} + +export const createConfig = new Command('create') + .description('Create a new ebalts config for an existing mint') + .requiredOption('-m, --mint ', 'Mint address') + .option('-g, --gating-program ', 'Gating program address') + //.option('-p, --payer ', 'Payer address') + //.option('-a, --authority ', 'Authority address') + .action(async (options: CreateConfigOptions, command) => { + const spinner = ora('Creating ebalts config...').start(); + + try { + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; + const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); + const kp = await loadKeypair(options.keypair); + + console.log(options); + console.log(parentOpts); + + const gatingProgram = (options.gatingProgram || '11111111111111111111111111111111') as Address; + + const {transaction, mintConfig} = await getCreateConfigTransaction({ + rpc, + payer: kp, + authority: kp, + mint: options.mint as Address, + gatingProgram, + }); + + + spinner.text = 'Signing transaction...'; + + // Sign the transaction + const signedTransaction = + await signTransactionMessageWithSigners(transaction); + + spinner.text = 'Sending transaction...'; + + // Send and confirm transaction + const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + + spinner.succeed('Ebalts config created successfully!'); + + // Display results + console.log(chalk.green('✅ Ebalts config created successfully!')); + console.log(chalk.cyan('📋 Details:')); + console.log(` ${chalk.bold('Mint:')} ${options.mint}`); + console.log(` ${chalk.bold('Gating Program:')} ${options.gatingProgram}`); + console.log(` ${chalk.bold('Mint Config:')} ${mintConfig}`); + console.log(` ${chalk.bold('Transaction:')} ${signature}`); + } + catch (error) { + spinner.fail('Failed to create ebalts config'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + console.error( + chalk.red('❌ Error:'), + error + ); + console.error( + chalk.red('❌ Error:'), + error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); \ No newline at end of file diff --git a/packages/cli/src/commands/ebalts/ebalts.ts b/packages/cli/src/commands/ebalts/ebalts.ts new file mode 100644 index 0000000..1db6058 --- /dev/null +++ b/packages/cli/src/commands/ebalts/ebalts.ts @@ -0,0 +1,11 @@ +import { Command } from 'commander'; +import { createConfig } from './createConfig.js'; +import { setGatingProgram } from './setGatingProgram.js'; +import { thawPermissionless } from './thawPermissionless.js'; +import { enablePermissionlessThaw } from './enablePermissionlessThaw.js'; + +export const ebaltsCommand = new Command('ebalts') + .addCommand(createConfig) + .addCommand(setGatingProgram) + .addCommand(thawPermissionless) + .addCommand(enablePermissionlessThaw); \ No newline at end of file diff --git a/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts new file mode 100644 index 0000000..b446f2f --- /dev/null +++ b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts @@ -0,0 +1,88 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +import ora from 'ora'; +import { createArcadeTokenInitTransaction, getEnablePermissionlessThawTransaction } from '@mosaic/sdk'; +import { createSolanaClient } from '../../utils/rpc.js'; +import { loadKeypair } from '../../utils/solana.js'; +import { + compressTransactionMessageUsingAddressLookupTables, + createTransaction, + generateKeyPairSigner, + signTransactionMessageWithSigners, + SolanaError, + type Address, +} from 'gill'; +import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction, getTogglePermissionlessInstructionsInstruction } from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from './util.js'; + +interface CreateConfigOptions { + mint: string; + gatingProgram: string; + rpcUrl?: string; + keypair?: string; +} + +export const enablePermissionlessThaw = new Command('enable-permissionless-thaw') + .description('Enable permissionless thaw for an existing mint') + .requiredOption('-m, --mint ', 'Mint address') + .action(async (options: CreateConfigOptions, command) => { + const spinner = ora('Enabling permissionless thaw...').start(); + + try { + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; + const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); + const kp = await loadKeypair(options.keypair); + + console.log(options); + console.log(parentOpts); + + spinner.text = 'Building transaction...'; + + const transaction = await getEnablePermissionlessThawTransaction({ + rpc, + payer: kp, + authority: kp, + mint: options.mint as Address, + }); + + + spinner.text = 'Signing transaction...'; + + // Sign the transaction + const signedTransaction = + await signTransactionMessageWithSigners(transaction); + + spinner.text = 'Sending transaction...'; + + // Send and confirm transaction + const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + + spinner.succeed('Permissionless thaw enabled successfully!'); + + // Display results + console.log(chalk.green('✅ Permissionless thaw enabled successfully!')); + console.log(chalk.cyan('📋 Details:')); + console.log(` ${chalk.bold('Mint:')} ${options.mint}`); + console.log(` ${chalk.bold('Transaction:')} ${signature}`); + } + catch (error) { + spinner.fail('Failed to create ebalts config'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + console.error( + chalk.red('❌ Error:'), + error + ); + console.error( + chalk.red('❌ Error:'), + error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); \ No newline at end of file diff --git a/packages/cli/src/commands/ebalts/setGatingProgram.ts b/packages/cli/src/commands/ebalts/setGatingProgram.ts new file mode 100644 index 0000000..1dc8bb5 --- /dev/null +++ b/packages/cli/src/commands/ebalts/setGatingProgram.ts @@ -0,0 +1,96 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +import ora from 'ora'; +import { createArcadeTokenInitTransaction, getSetGatingProgramTransaction } from '@mosaic/sdk'; +import { createSolanaClient } from '../../utils/rpc.js'; +import { loadKeypair } from '../../utils/solana.js'; +import { + compressTransactionMessageUsingAddressLookupTables, + createTransaction, + generateKeyPairSigner, + signTransactionMessageWithSigners, + SolanaError, + type Address, +} from 'gill'; +import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction } from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from './util.js'; + +interface CreateConfigOptions { + mint: string; + gatingProgram: string; + rpcUrl?: string; + keypair?: string; +} + +export const setGatingProgram = new Command('set-gating-program') + .description('Set the gating program for an existing mint') + .requiredOption('-m, --mint ', 'Mint address') + .requiredOption('-g, --gating-program ', 'Gating program address') + .action(async (options: CreateConfigOptions, command) => { + const spinner = ora('Setting gating program...').start(); + + try { + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; + const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); + const kp = await loadKeypair(options.keypair); + + console.log(options); + console.log(parentOpts); + + const signerAddress = kp.address; + + const mintConfigPda = await findMintConfigPda({ mint: options.mint as Address }, { programAddress: EBALTS_PROGRAM_ID }); + const gatingProgram = (options.gatingProgram || '11111111111111111111111111111111') as Address; + + + const transaction = await getSetGatingProgramTransaction({ + rpc, + payer: kp, + authority: kp, + mint: options.mint as Address, + gatingProgram: gatingProgram, + }); + + + spinner.text = 'Signing transaction...'; + + // Sign the transaction + const signedTransaction = + await signTransactionMessageWithSigners(transaction); + + spinner.text = 'Sending transaction...'; + + // Send and confirm transaction + const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + + spinner.succeed('Ebalts config created successfully!'); + + // Display results + console.log(chalk.green('✅ Ebalts config created successfully!')); + console.log(chalk.cyan('📋 Details:')); + console.log(` ${chalk.bold('Mint:')} ${options.mint}`); + console.log(` ${chalk.bold('Gating Program:')} ${options.gatingProgram}`); + console.log(` ${chalk.bold('Mint Config:')} ${mintConfigPda[0]}`); + console.log(` ${chalk.bold('Transaction:')} ${signature}`); + } + catch (error) { + spinner.fail('Failed to create ebalts config'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + console.error( + chalk.red('❌ Error:'), + error + ); + console.error( + chalk.red('❌ Error:'), + error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); \ No newline at end of file diff --git a/packages/cli/src/commands/ebalts/thawPermissionless.ts b/packages/cli/src/commands/ebalts/thawPermissionless.ts new file mode 100644 index 0000000..4bafacc --- /dev/null +++ b/packages/cli/src/commands/ebalts/thawPermissionless.ts @@ -0,0 +1,104 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +import ora from 'ora'; +import { createArcadeTokenInitTransaction, getThawPermissionlessTransaction } from '@mosaic/sdk'; +import { createSolanaClient } from '../../utils/rpc.js'; +import { loadKeypair } from '../../utils/solana.js'; +import { + compressTransactionMessageUsingAddressLookupTables, + createTransaction, + generateKeyPairSigner, + signTransactionMessageWithSigners, + SolanaError, + type Address, + AccountRole, + fetchEncodedAccount, + lamports, +} from 'gill'; +import { createThawPermissionlessInstructionWithExtraMetas, findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction } from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from './util.js'; +import { AccountState, getAssociatedTokenAccountAddress, getTokenEncoder, TOKEN_2022_PROGRAM_ADDRESS } from 'gill/programs/token'; +import { ABL_PROGRAM_ID } from '../abl/utils.js'; +import { findABWalletPda } from '@mosaic/abl'; + +interface CreateConfigOptions { + mint: string; + rpcUrl?: string; + keypair?: string; +} + +export const thawPermissionless = new Command('thaw-permissionless') + .description('Thaw permissionless eoas for an existing mint') + .requiredOption('-m, --mint ', 'Mint address') + .action(async (options: CreateConfigOptions, command) => { + const spinner = ora('Thawing permissionless...').start(); + + try { + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; + const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); + const kp = await loadKeypair(options.keypair); + + console.log(options); + console.log(parentOpts); + + const signerAddress = kp.address; + const mint = options.mint as Address; + + spinner.text = 'Building transaction...'; + + const ata = await getAssociatedTokenAccountAddress( + mint, + signerAddress, + TOKEN_2022_PROGRAM_ADDRESS + ); + + const transaction = await getThawPermissionlessTransaction({ + rpc, + payer: kp, + authority: kp, + mint, + tokenAccount: ata, + tokenAccountOwner: signerAddress, + }); + + + spinner.text = 'Signing transaction...'; + + // Sign the transaction + const signedTransaction = + await signTransactionMessageWithSigners(transaction); + + spinner.text = 'Sending transaction...'; + + // Send and confirm transaction + const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + + spinner.succeed('Permissionless thawed successfully!'); + + // Display results + console.log(chalk.green('✅ Permissionless thawed successfully!')); + console.log(chalk.cyan('📋 Details:')); + console.log(` ${chalk.bold('Token Account:')} ${ata}`); + console.log(` ${chalk.bold('Transaction:')} ${signature}`); + } + catch (error) { + spinner.fail('Failed to create ebalts config'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + console.error( + chalk.red('❌ Error:'), + error + ); + console.error( + chalk.red('❌ Error:'), + error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); \ No newline at end of file diff --git a/packages/cli/src/commands/ebalts/util.ts b/packages/cli/src/commands/ebalts/util.ts new file mode 100644 index 0000000..9cdcc46 --- /dev/null +++ b/packages/cli/src/commands/ebalts/util.ts @@ -0,0 +1,4 @@ +import type { Address } from "gill"; + + +export const EBALTS_PROGRAM_ID = '81H44JYqk1p8RUks7pNJjhQG4Pj8FcaJeTUxZKN3JfLc' as Address; \ No newline at end of file diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 188ca49..c91ea2f 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -8,6 +8,8 @@ import { freezeCommand } from './commands/freeze.js'; import { thawCommand } from './commands/thaw.js'; import { forceTransferCommand } from './commands/force-transfer.js'; import { inspectMintCommand } from './commands/inspect-mint.js'; +import { ebaltsCommand } from './commands/ebalts/ebalts.js'; +import { ablCommand } from './commands/abl/abl.js'; const program = new Command(); @@ -31,13 +33,15 @@ program.addCommand(freezeCommand); program.addCommand(thawCommand); program.addCommand(forceTransferCommand); program.addCommand(inspectMintCommand); +program.addCommand(ebaltsCommand); +program.addCommand(ablCommand); // Global options program .option('--rpc-url ', 'Solana RPC URL', 'https://api.devnet.solana.com') .option( '--keypair ', - 'Path to keypair file (defaults to Solana CLI default)' + 'Path to keypair file (defaults to Solana CLI default)', ); program.parse(process.argv); diff --git a/packages/ebalts/README.md b/packages/ebalts/README.md new file mode 100644 index 0000000..e69de29 diff --git a/packages/ebalts/jest.config.js b/packages/ebalts/jest.config.js new file mode 100644 index 0000000..38e2b68 --- /dev/null +++ b/packages/ebalts/jest.config.js @@ -0,0 +1,29 @@ +/** @type {import('jest').Config} */ +export default { + preset: 'ts-jest/presets/default-esm', + extensionsToTreatAsEsm: ['.ts'], + testEnvironment: 'node', + roots: ['/src'], + testMatch: ['**/__tests__/**/*.test.ts', '**/?(*.)+(spec|test).ts'], + transform: { + '^.+\\.ts$': [ + 'ts-jest', + { + useESM: true, + }, + ], + }, + collectCoverageFrom: [ + 'src/**/*.ts', + '!src/**/*.d.ts', + '!src/**/__tests__/**/*.test.ts', + '!src/**/*.test.ts', + '!src/**/__tests__/setup.ts', + '!src/**/__tests__/test-utils.ts', + ], + moduleNameMapper: { + '^@/(.*)$': '/src/$1', + }, + moduleFileExtensions: ['ts', 'js', 'json'], + setupFilesAfterEnv: ['/src/__tests__/setup.ts'], +}; diff --git a/packages/ebalts/package.json b/packages/ebalts/package.json new file mode 100644 index 0000000..5bda1d1 --- /dev/null +++ b/packages/ebalts/package.json @@ -0,0 +1,51 @@ +{ + "name": "@mosaic/ebalts", + "version": "0.1.0", + "description": "SDK for Mosaic with helper functions for issuance and management of any token", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsc", + "dev": "echo 'Dev will be implemented'", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "lint": "eslint src --ext .ts", + "lint:fix": "eslint src --ext .ts --fix", + "type-check": "tsc --noEmit", + "clean": "rm -rf dist" + }, + "dependencies": { + "gill": "^0.10.2", + "@solana/kit": "2.3.0", + "@mosaic/tlv-account-resolution": "workspace:*" + }, + "devDependencies": { + "@types/jest": "^29.5.0", + "@typescript-eslint/eslint-plugin": "^8.34.0", + "@typescript-eslint/parser": "^8.34.0", + "eslint": "^9.32.0", + "jest": "^29.5.0", + "ts-jest": "^29.1.0" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "keywords": [ + "solana", + "token-2022", + "extensions", + "core", + "hooks" + ] +} diff --git a/packages/ebalts/src/generated/accounts/index.ts b/packages/ebalts/src/generated/accounts/index.ts new file mode 100644 index 0000000..ae5a9a7 --- /dev/null +++ b/packages/ebalts/src/generated/accounts/index.ts @@ -0,0 +1,9 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './mintConfig'; diff --git a/packages/ebalts/src/generated/accounts/mintConfig.ts b/packages/ebalts/src/generated/accounts/mintConfig.ts new file mode 100644 index 0000000..d542e32 --- /dev/null +++ b/packages/ebalts/src/generated/accounts/mintConfig.ts @@ -0,0 +1,169 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + assertAccountExists, + assertAccountsExist, + combineCodec, + decodeAccount, + fetchEncodedAccount, + fetchEncodedAccounts, + getAddressDecoder, + getAddressEncoder, + getBooleanDecoder, + getBooleanEncoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Account, + type Address, + type Codec, + type Decoder, + type EncodedAccount, + type Encoder, + type FetchAccountConfig, + type FetchAccountsConfig, + type MaybeAccount, + type MaybeEncodedAccount, +} from '@solana/kit'; +import { MintConfigSeeds, findMintConfigPda } from '../pdas'; + +export const MINT_CONFIG_DISCRIMINATOR = 1; + +export function getMintConfigDiscriminatorBytes() { + return getU8Encoder().encode(MINT_CONFIG_DISCRIMINATOR); +} + +export type MintConfig = { + discriminator: number; + mint: Address; + freezeAuthority: Address; + gatingProgram: Address; + bump: number; + enablePermissionlessThaw: boolean; + enablePermissionlessFreeze: boolean; +}; + +export type MintConfigArgs = { + mint: Address; + freezeAuthority: Address; + gatingProgram: Address; + bump: number; + enablePermissionlessThaw: boolean; + enablePermissionlessFreeze: boolean; +}; + +export function getMintConfigEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['mint', getAddressEncoder()], + ['freezeAuthority', getAddressEncoder()], + ['gatingProgram', getAddressEncoder()], + ['bump', getU8Encoder()], + ['enablePermissionlessThaw', getBooleanEncoder()], + ['enablePermissionlessFreeze', getBooleanEncoder()], + ]), + (value) => ({ ...value, discriminator: MINT_CONFIG_DISCRIMINATOR }) + ); +} + +export function getMintConfigDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['mint', getAddressDecoder()], + ['freezeAuthority', getAddressDecoder()], + ['gatingProgram', getAddressDecoder()], + ['bump', getU8Decoder()], + ['enablePermissionlessThaw', getBooleanDecoder()], + ['enablePermissionlessFreeze', getBooleanDecoder()], + ]); +} + +export function getMintConfigCodec(): Codec { + return combineCodec(getMintConfigEncoder(), getMintConfigDecoder()); +} + +export function decodeMintConfig( + encodedAccount: EncodedAccount +): Account; +export function decodeMintConfig( + encodedAccount: MaybeEncodedAccount +): MaybeAccount; +export function decodeMintConfig( + encodedAccount: EncodedAccount | MaybeEncodedAccount +): Account | MaybeAccount { + return decodeAccount( + encodedAccount as MaybeEncodedAccount, + getMintConfigDecoder() + ); +} + +export async function fetchMintConfig( + rpc: Parameters[0], + address: Address, + config?: FetchAccountConfig +): Promise> { + const maybeAccount = await fetchMaybeMintConfig(rpc, address, config); + assertAccountExists(maybeAccount); + return maybeAccount; +} + +export async function fetchMaybeMintConfig( + rpc: Parameters[0], + address: Address, + config?: FetchAccountConfig +): Promise> { + const maybeAccount = await fetchEncodedAccount(rpc, address, config); + return decodeMintConfig(maybeAccount); +} + +export async function fetchAllMintConfig( + rpc: Parameters[0], + addresses: Array
, + config?: FetchAccountsConfig +): Promise[]> { + const maybeAccounts = await fetchAllMaybeMintConfig(rpc, addresses, config); + assertAccountsExist(maybeAccounts); + return maybeAccounts; +} + +export async function fetchAllMaybeMintConfig( + rpc: Parameters[0], + addresses: Array
, + config?: FetchAccountsConfig +): Promise[]> { + const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config); + return maybeAccounts.map((maybeAccount) => decodeMintConfig(maybeAccount)); +} + +export function getMintConfigSize(): number { + return 0; +} + +export async function fetchMintConfigFromSeeds( + rpc: Parameters[0], + seeds: MintConfigSeeds, + config: FetchAccountConfig & { programAddress?: Address } = {} +): Promise> { + const maybeAccount = await fetchMaybeMintConfigFromSeeds(rpc, seeds, config); + assertAccountExists(maybeAccount); + return maybeAccount; +} + +export async function fetchMaybeMintConfigFromSeeds( + rpc: Parameters[0], + seeds: MintConfigSeeds, + config: FetchAccountConfig & { programAddress?: Address } = {} +): Promise> { + const { programAddress, ...fetchConfig } = config; + const [address] = await findMintConfigPda(seeds, { programAddress }); + return await fetchMaybeMintConfig(rpc, address, fetchConfig); +} diff --git a/packages/ebalts/src/generated/index.ts b/packages/ebalts/src/generated/index.ts new file mode 100644 index 0000000..1002b82 --- /dev/null +++ b/packages/ebalts/src/generated/index.ts @@ -0,0 +1,12 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './accounts'; +export * from './instructions'; +export * from './pdas'; +export * from './programs'; diff --git a/packages/ebalts/src/generated/instructions/createConfig.ts b/packages/ebalts/src/generated/instructions/createConfig.ts new file mode 100644 index 0000000..efbcfae --- /dev/null +++ b/packages/ebalts/src/generated/instructions/createConfig.ts @@ -0,0 +1,262 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getAddressDecoder, + getAddressEncoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/kit'; +import { EBALTS_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const CREATE_CONFIG_DISCRIMINATOR = 0; + +export function getCreateConfigDiscriminatorBytes() { + return getU8Encoder().encode(CREATE_CONFIG_DISCRIMINATOR); +} + +export type CreateConfigInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountPayer extends string | IAccountMeta = string, + TAccountAuthority extends string | IAccountMeta = string, + TAccountMint extends string | IAccountMeta = string, + TAccountMintConfig extends string | IAccountMeta = string, + TAccountSystemProgram extends + | string + | IAccountMeta = '11111111111111111111111111111111', + TAccountTokenProgram extends + | string + | IAccountMeta = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountPayer extends string + ? WritableAccount + : TAccountPayer, + TAccountAuthority extends string + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority, + TAccountMint extends string + ? WritableAccount + : TAccountMint, + TAccountMintConfig extends string + ? WritableAccount + : TAccountMintConfig, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + TAccountTokenProgram extends string + ? ReadonlyAccount + : TAccountTokenProgram, + ...TRemainingAccounts, + ] + >; + +export type CreateConfigInstructionData = { + discriminator: number; + gatingProgram: Address; +}; + +export type CreateConfigInstructionDataArgs = { gatingProgram: Address }; + +export function getCreateConfigInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['gatingProgram', getAddressEncoder()], + ]), + (value) => ({ ...value, discriminator: CREATE_CONFIG_DISCRIMINATOR }) + ); +} + +export function getCreateConfigInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['gatingProgram', getAddressDecoder()], + ]); +} + +export function getCreateConfigInstructionDataCodec(): Codec< + CreateConfigInstructionDataArgs, + CreateConfigInstructionData +> { + return combineCodec( + getCreateConfigInstructionDataEncoder(), + getCreateConfigInstructionDataDecoder() + ); +} + +export type CreateConfigInput< + TAccountPayer extends string = string, + TAccountAuthority extends string = string, + TAccountMint extends string = string, + TAccountMintConfig extends string = string, + TAccountSystemProgram extends string = string, + TAccountTokenProgram extends string = string, +> = { + payer: Address; + authority: TransactionSigner; + mint: Address; + mintConfig: Address; + systemProgram?: Address; + tokenProgram?: Address; + gatingProgram: CreateConfigInstructionDataArgs['gatingProgram']; +}; + +export function getCreateConfigInstruction< + TAccountPayer extends string, + TAccountAuthority extends string, + TAccountMint extends string, + TAccountMintConfig extends string, + TAccountSystemProgram extends string, + TAccountTokenProgram extends string, + TProgramAddress extends Address = typeof EBALTS_PROGRAM_ADDRESS, +>( + input: CreateConfigInput< + TAccountPayer, + TAccountAuthority, + TAccountMint, + TAccountMintConfig, + TAccountSystemProgram, + TAccountTokenProgram + >, + config?: { programAddress?: TProgramAddress } +): CreateConfigInstruction< + TProgramAddress, + TAccountPayer, + TAccountAuthority, + TAccountMint, + TAccountMintConfig, + TAccountSystemProgram, + TAccountTokenProgram +> { + // Program address. + const programAddress = config?.programAddress ?? EBALTS_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + payer: { value: input.payer ?? null, isWritable: true }, + authority: { value: input.authority ?? null, isWritable: false }, + mint: { value: input.mint ?? null, isWritable: true }, + mintConfig: { value: input.mintConfig ?? null, isWritable: true }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + tokenProgram: { value: input.tokenProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Resolve default values. + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + if (!accounts.tokenProgram.value) { + accounts.tokenProgram.value = + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' as Address<'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.payer), + getAccountMeta(accounts.authority), + getAccountMeta(accounts.mint), + getAccountMeta(accounts.mintConfig), + getAccountMeta(accounts.systemProgram), + getAccountMeta(accounts.tokenProgram), + ], + programAddress, + data: getCreateConfigInstructionDataEncoder().encode( + args as CreateConfigInstructionDataArgs + ), + } as CreateConfigInstruction< + TProgramAddress, + TAccountPayer, + TAccountAuthority, + TAccountMint, + TAccountMintConfig, + TAccountSystemProgram, + TAccountTokenProgram + >; + + return instruction; +} + +export type ParsedCreateConfigInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + payer: TAccountMetas[0]; + authority: TAccountMetas[1]; + mint: TAccountMetas[2]; + mintConfig: TAccountMetas[3]; + systemProgram: TAccountMetas[4]; + tokenProgram: TAccountMetas[5]; + }; + data: CreateConfigInstructionData; +}; + +export function parseCreateConfigInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedCreateConfigInstruction { + if (instruction.accounts.length < 6) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + payer: getNextAccount(), + authority: getNextAccount(), + mint: getNextAccount(), + mintConfig: getNextAccount(), + systemProgram: getNextAccount(), + tokenProgram: getNextAccount(), + }, + data: getCreateConfigInstructionDataDecoder().decode(instruction.data), + }; +} diff --git a/packages/ebalts/src/generated/instructions/forfeitFreezeAuthority.ts b/packages/ebalts/src/generated/instructions/forfeitFreezeAuthority.ts new file mode 100644 index 0000000..3174bdf --- /dev/null +++ b/packages/ebalts/src/generated/instructions/forfeitFreezeAuthority.ts @@ -0,0 +1,235 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getAddressDecoder, + getAddressEncoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/kit'; +import { EBALTS_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const FORFEIT_FREEZE_AUTHORITY_DISCRIMINATOR = 3; + +export function getForfeitFreezeAuthorityDiscriminatorBytes() { + return getU8Encoder().encode(FORFEIT_FREEZE_AUTHORITY_DISCRIMINATOR); +} + +export type ForfeitFreezeAuthorityInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountAuthority extends string | IAccountMeta = string, + TAccountMint extends string | IAccountMeta = string, + TAccountMintConfig extends string | IAccountMeta = string, + TAccountTokenProgram extends + | string + | IAccountMeta = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountAuthority extends string + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority, + TAccountMint extends string + ? WritableAccount + : TAccountMint, + TAccountMintConfig extends string + ? WritableAccount + : TAccountMintConfig, + TAccountTokenProgram extends string + ? ReadonlyAccount + : TAccountTokenProgram, + ...TRemainingAccounts, + ] + >; + +export type ForfeitFreezeAuthorityInstructionData = { + discriminator: number; + newFreezeAuthority: Address; +}; + +export type ForfeitFreezeAuthorityInstructionDataArgs = { + newFreezeAuthority: Address; +}; + +export function getForfeitFreezeAuthorityInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['newFreezeAuthority', getAddressEncoder()], + ]), + (value) => ({ + ...value, + discriminator: FORFEIT_FREEZE_AUTHORITY_DISCRIMINATOR, + }) + ); +} + +export function getForfeitFreezeAuthorityInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['newFreezeAuthority', getAddressDecoder()], + ]); +} + +export function getForfeitFreezeAuthorityInstructionDataCodec(): Codec< + ForfeitFreezeAuthorityInstructionDataArgs, + ForfeitFreezeAuthorityInstructionData +> { + return combineCodec( + getForfeitFreezeAuthorityInstructionDataEncoder(), + getForfeitFreezeAuthorityInstructionDataDecoder() + ); +} + +export type ForfeitFreezeAuthorityInput< + TAccountAuthority extends string = string, + TAccountMint extends string = string, + TAccountMintConfig extends string = string, + TAccountTokenProgram extends string = string, +> = { + authority: TransactionSigner; + mint: Address; + mintConfig: Address; + tokenProgram?: Address; + newFreezeAuthority: ForfeitFreezeAuthorityInstructionDataArgs['newFreezeAuthority']; +}; + +export function getForfeitFreezeAuthorityInstruction< + TAccountAuthority extends string, + TAccountMint extends string, + TAccountMintConfig extends string, + TAccountTokenProgram extends string, + TProgramAddress extends Address = typeof EBALTS_PROGRAM_ADDRESS, +>( + input: ForfeitFreezeAuthorityInput< + TAccountAuthority, + TAccountMint, + TAccountMintConfig, + TAccountTokenProgram + >, + config?: { programAddress?: TProgramAddress } +): ForfeitFreezeAuthorityInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountMintConfig, + TAccountTokenProgram +> { + // Program address. + const programAddress = config?.programAddress ?? EBALTS_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: false }, + mint: { value: input.mint ?? null, isWritable: true }, + mintConfig: { value: input.mintConfig ?? null, isWritable: true }, + tokenProgram: { value: input.tokenProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Resolve default values. + if (!accounts.tokenProgram.value) { + accounts.tokenProgram.value = + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' as Address<'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.mint), + getAccountMeta(accounts.mintConfig), + getAccountMeta(accounts.tokenProgram), + ], + programAddress, + data: getForfeitFreezeAuthorityInstructionDataEncoder().encode( + args as ForfeitFreezeAuthorityInstructionDataArgs + ), + } as ForfeitFreezeAuthorityInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountMintConfig, + TAccountTokenProgram + >; + + return instruction; +} + +export type ParsedForfeitFreezeAuthorityInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + mint: TAccountMetas[1]; + mintConfig: TAccountMetas[2]; + tokenProgram: TAccountMetas[3]; + }; + data: ForfeitFreezeAuthorityInstructionData; +}; + +export function parseForfeitFreezeAuthorityInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedForfeitFreezeAuthorityInstruction { + if (instruction.accounts.length < 4) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + mint: getNextAccount(), + mintConfig: getNextAccount(), + tokenProgram: getNextAccount(), + }, + data: getForfeitFreezeAuthorityInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/packages/ebalts/src/generated/instructions/freeze.ts b/packages/ebalts/src/generated/instructions/freeze.ts new file mode 100644 index 0000000..1a9d819 --- /dev/null +++ b/packages/ebalts/src/generated/instructions/freeze.ts @@ -0,0 +1,225 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/kit'; +import { EBALTS_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const FREEZE_DISCRIMINATOR = 5; + +export function getFreezeDiscriminatorBytes() { + return getU8Encoder().encode(FREEZE_DISCRIMINATOR); +} + +export type FreezeInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountAuthority extends string | IAccountMeta = string, + TAccountMint extends string | IAccountMeta = string, + TAccountTokenAccount extends string | IAccountMeta = string, + TAccountMintConfig extends string | IAccountMeta = string, + TAccountTokenProgram extends + | string + | IAccountMeta = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountAuthority extends string + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority, + TAccountMint extends string + ? ReadonlyAccount + : TAccountMint, + TAccountTokenAccount extends string + ? WritableAccount + : TAccountTokenAccount, + TAccountMintConfig extends string + ? ReadonlyAccount + : TAccountMintConfig, + TAccountTokenProgram extends string + ? ReadonlyAccount + : TAccountTokenProgram, + ...TRemainingAccounts, + ] + >; + +export type FreezeInstructionData = { discriminator: number }; + +export type FreezeInstructionDataArgs = {}; + +export function getFreezeInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([['discriminator', getU8Encoder()]]), + (value) => ({ ...value, discriminator: FREEZE_DISCRIMINATOR }) + ); +} + +export function getFreezeInstructionDataDecoder(): Decoder { + return getStructDecoder([['discriminator', getU8Decoder()]]); +} + +export function getFreezeInstructionDataCodec(): Codec< + FreezeInstructionDataArgs, + FreezeInstructionData +> { + return combineCodec( + getFreezeInstructionDataEncoder(), + getFreezeInstructionDataDecoder() + ); +} + +export type FreezeInput< + TAccountAuthority extends string = string, + TAccountMint extends string = string, + TAccountTokenAccount extends string = string, + TAccountMintConfig extends string = string, + TAccountTokenProgram extends string = string, +> = { + authority: TransactionSigner; + mint: Address; + tokenAccount: Address; + mintConfig: Address; + tokenProgram?: Address; +}; + +export function getFreezeInstruction< + TAccountAuthority extends string, + TAccountMint extends string, + TAccountTokenAccount extends string, + TAccountMintConfig extends string, + TAccountTokenProgram extends string, + TProgramAddress extends Address = typeof EBALTS_PROGRAM_ADDRESS, +>( + input: FreezeInput< + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountMintConfig, + TAccountTokenProgram + >, + config?: { programAddress?: TProgramAddress } +): FreezeInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountMintConfig, + TAccountTokenProgram +> { + // Program address. + const programAddress = config?.programAddress ?? EBALTS_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: false }, + mint: { value: input.mint ?? null, isWritable: false }, + tokenAccount: { value: input.tokenAccount ?? null, isWritable: true }, + mintConfig: { value: input.mintConfig ?? null, isWritable: false }, + tokenProgram: { value: input.tokenProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Resolve default values. + if (!accounts.tokenProgram.value) { + accounts.tokenProgram.value = + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' as Address<'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.mint), + getAccountMeta(accounts.tokenAccount), + getAccountMeta(accounts.mintConfig), + getAccountMeta(accounts.tokenProgram), + ], + programAddress, + data: getFreezeInstructionDataEncoder().encode({}), + } as FreezeInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountMintConfig, + TAccountTokenProgram + >; + + return instruction; +} + +export type ParsedFreezeInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + mint: TAccountMetas[1]; + tokenAccount: TAccountMetas[2]; + mintConfig: TAccountMetas[3]; + tokenProgram: TAccountMetas[4]; + }; + data: FreezeInstructionData; +}; + +export function parseFreezeInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedFreezeInstruction { + if (instruction.accounts.length < 5) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + mint: getNextAccount(), + tokenAccount: getNextAccount(), + mintConfig: getNextAccount(), + tokenProgram: getNextAccount(), + }, + data: getFreezeInstructionDataDecoder().decode(instruction.data), + }; +} diff --git a/packages/ebalts/src/generated/instructions/freezePermissionless.ts b/packages/ebalts/src/generated/instructions/freezePermissionless.ts new file mode 100644 index 0000000..9ef47e8 --- /dev/null +++ b/packages/ebalts/src/generated/instructions/freezePermissionless.ts @@ -0,0 +1,261 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/kit'; +import { EBALTS_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const FREEZE_PERMISSIONLESS_DISCRIMINATOR = 7; + +export function getFreezePermissionlessDiscriminatorBytes() { + return getU8Encoder().encode(FREEZE_PERMISSIONLESS_DISCRIMINATOR); +} + +export type FreezePermissionlessInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountAuthority extends string | IAccountMeta = string, + TAccountMint extends string | IAccountMeta = string, + TAccountTokenAccount extends string | IAccountMeta = string, + TAccountTokenAccountOwner extends string | IAccountMeta = string, + TAccountMintConfig extends string | IAccountMeta = string, + TAccountTokenProgram extends + | string + | IAccountMeta = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + TAccountGatingProgram extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountAuthority extends string + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority, + TAccountMint extends string + ? ReadonlyAccount + : TAccountMint, + TAccountTokenAccount extends string + ? WritableAccount + : TAccountTokenAccount, + TAccountTokenAccountOwner extends string + ? ReadonlyAccount + : TAccountTokenAccountOwner, + TAccountMintConfig extends string + ? ReadonlyAccount + : TAccountMintConfig, + TAccountTokenProgram extends string + ? ReadonlyAccount + : TAccountTokenProgram, + TAccountGatingProgram extends string + ? ReadonlyAccount + : TAccountGatingProgram, + ...TRemainingAccounts, + ] + >; + +export type FreezePermissionlessInstructionData = { discriminator: number }; + +export type FreezePermissionlessInstructionDataArgs = {}; + +export function getFreezePermissionlessInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([['discriminator', getU8Encoder()]]), + (value) => ({ + ...value, + discriminator: FREEZE_PERMISSIONLESS_DISCRIMINATOR, + }) + ); +} + +export function getFreezePermissionlessInstructionDataDecoder(): Decoder { + return getStructDecoder([['discriminator', getU8Decoder()]]); +} + +export function getFreezePermissionlessInstructionDataCodec(): Codec< + FreezePermissionlessInstructionDataArgs, + FreezePermissionlessInstructionData +> { + return combineCodec( + getFreezePermissionlessInstructionDataEncoder(), + getFreezePermissionlessInstructionDataDecoder() + ); +} + +export type FreezePermissionlessInput< + TAccountAuthority extends string = string, + TAccountMint extends string = string, + TAccountTokenAccount extends string = string, + TAccountTokenAccountOwner extends string = string, + TAccountMintConfig extends string = string, + TAccountTokenProgram extends string = string, + TAccountGatingProgram extends string = string, +> = { + authority: TransactionSigner; + mint: Address; + tokenAccount: Address; + tokenAccountOwner: Address; + mintConfig: Address; + tokenProgram?: Address; + gatingProgram: Address; +}; + +export function getFreezePermissionlessInstruction< + TAccountAuthority extends string, + TAccountMint extends string, + TAccountTokenAccount extends string, + TAccountTokenAccountOwner extends string, + TAccountMintConfig extends string, + TAccountTokenProgram extends string, + TAccountGatingProgram extends string, + TProgramAddress extends Address = typeof EBALTS_PROGRAM_ADDRESS, +>( + input: FreezePermissionlessInput< + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountTokenAccountOwner, + TAccountMintConfig, + TAccountTokenProgram, + TAccountGatingProgram + >, + config?: { programAddress?: TProgramAddress } +): FreezePermissionlessInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountTokenAccountOwner, + TAccountMintConfig, + TAccountTokenProgram, + TAccountGatingProgram +> { + // Program address. + const programAddress = config?.programAddress ?? EBALTS_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: false }, + mint: { value: input.mint ?? null, isWritable: false }, + tokenAccount: { value: input.tokenAccount ?? null, isWritable: true }, + tokenAccountOwner: { + value: input.tokenAccountOwner ?? null, + isWritable: false, + }, + mintConfig: { value: input.mintConfig ?? null, isWritable: false }, + tokenProgram: { value: input.tokenProgram ?? null, isWritable: false }, + gatingProgram: { value: input.gatingProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Resolve default values. + if (!accounts.tokenProgram.value) { + accounts.tokenProgram.value = + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' as Address<'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.mint), + getAccountMeta(accounts.tokenAccount), + getAccountMeta(accounts.tokenAccountOwner), + getAccountMeta(accounts.mintConfig), + getAccountMeta(accounts.tokenProgram), + getAccountMeta(accounts.gatingProgram), + ], + programAddress, + data: getFreezePermissionlessInstructionDataEncoder().encode({}), + } as FreezePermissionlessInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountTokenAccountOwner, + TAccountMintConfig, + TAccountTokenProgram, + TAccountGatingProgram + >; + + return instruction; +} + +export type ParsedFreezePermissionlessInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + mint: TAccountMetas[1]; + tokenAccount: TAccountMetas[2]; + tokenAccountOwner: TAccountMetas[3]; + mintConfig: TAccountMetas[4]; + tokenProgram: TAccountMetas[5]; + gatingProgram: TAccountMetas[6]; + }; + data: FreezePermissionlessInstructionData; +}; + +export function parseFreezePermissionlessInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedFreezePermissionlessInstruction { + if (instruction.accounts.length < 7) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + mint: getNextAccount(), + tokenAccount: getNextAccount(), + tokenAccountOwner: getNextAccount(), + mintConfig: getNextAccount(), + tokenProgram: getNextAccount(), + gatingProgram: getNextAccount(), + }, + data: getFreezePermissionlessInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/packages/ebalts/src/generated/instructions/index.ts b/packages/ebalts/src/generated/instructions/index.ts new file mode 100644 index 0000000..56db8e9 --- /dev/null +++ b/packages/ebalts/src/generated/instructions/index.ts @@ -0,0 +1,17 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './createConfig'; +export * from './forfeitFreezeAuthority'; +export * from './freeze'; +export * from './freezePermissionless'; +export * from './setAuthority'; +export * from './setGatingProgram'; +export * from './thaw'; +export * from './thawPermissionless'; +export * from './togglePermissionlessInstructions'; diff --git a/packages/ebalts/src/generated/instructions/setAuthority.ts b/packages/ebalts/src/generated/instructions/setAuthority.ts new file mode 100644 index 0000000..be78b4c --- /dev/null +++ b/packages/ebalts/src/generated/instructions/setAuthority.ts @@ -0,0 +1,188 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getAddressDecoder, + getAddressEncoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/kit'; +import { EBALTS_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const SET_AUTHORITY_DISCRIMINATOR = 1; + +export function getSetAuthorityDiscriminatorBytes() { + return getU8Encoder().encode(SET_AUTHORITY_DISCRIMINATOR); +} + +export type SetAuthorityInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountAuthority extends string | IAccountMeta = string, + TAccountMintConfig extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountAuthority extends string + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority, + TAccountMintConfig extends string + ? WritableAccount + : TAccountMintConfig, + ...TRemainingAccounts, + ] + >; + +export type SetAuthorityInstructionData = { + discriminator: number; + newAuthority: Address; +}; + +export type SetAuthorityInstructionDataArgs = { newAuthority: Address }; + +export function getSetAuthorityInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['newAuthority', getAddressEncoder()], + ]), + (value) => ({ ...value, discriminator: SET_AUTHORITY_DISCRIMINATOR }) + ); +} + +export function getSetAuthorityInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['newAuthority', getAddressDecoder()], + ]); +} + +export function getSetAuthorityInstructionDataCodec(): Codec< + SetAuthorityInstructionDataArgs, + SetAuthorityInstructionData +> { + return combineCodec( + getSetAuthorityInstructionDataEncoder(), + getSetAuthorityInstructionDataDecoder() + ); +} + +export type SetAuthorityInput< + TAccountAuthority extends string = string, + TAccountMintConfig extends string = string, +> = { + authority: TransactionSigner; + mintConfig: Address; + newAuthority: SetAuthorityInstructionDataArgs['newAuthority']; +}; + +export function getSetAuthorityInstruction< + TAccountAuthority extends string, + TAccountMintConfig extends string, + TProgramAddress extends Address = typeof EBALTS_PROGRAM_ADDRESS, +>( + input: SetAuthorityInput, + config?: { programAddress?: TProgramAddress } +): SetAuthorityInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMintConfig +> { + // Program address. + const programAddress = config?.programAddress ?? EBALTS_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: false }, + mintConfig: { value: input.mintConfig ?? null, isWritable: true }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.mintConfig), + ], + programAddress, + data: getSetAuthorityInstructionDataEncoder().encode( + args as SetAuthorityInstructionDataArgs + ), + } as SetAuthorityInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMintConfig + >; + + return instruction; +} + +export type ParsedSetAuthorityInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + mintConfig: TAccountMetas[1]; + }; + data: SetAuthorityInstructionData; +}; + +export function parseSetAuthorityInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedSetAuthorityInstruction { + if (instruction.accounts.length < 2) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + mintConfig: getNextAccount(), + }, + data: getSetAuthorityInstructionDataDecoder().decode(instruction.data), + }; +} diff --git a/packages/ebalts/src/generated/instructions/setGatingProgram.ts b/packages/ebalts/src/generated/instructions/setGatingProgram.ts new file mode 100644 index 0000000..d857e4a --- /dev/null +++ b/packages/ebalts/src/generated/instructions/setGatingProgram.ts @@ -0,0 +1,188 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getAddressDecoder, + getAddressEncoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/kit'; +import { EBALTS_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const SET_GATING_PROGRAM_DISCRIMINATOR = 2; + +export function getSetGatingProgramDiscriminatorBytes() { + return getU8Encoder().encode(SET_GATING_PROGRAM_DISCRIMINATOR); +} + +export type SetGatingProgramInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountAuthority extends string | IAccountMeta = string, + TAccountMintConfig extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountAuthority extends string + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority, + TAccountMintConfig extends string + ? WritableAccount + : TAccountMintConfig, + ...TRemainingAccounts, + ] + >; + +export type SetGatingProgramInstructionData = { + discriminator: number; + newGatingProgram: Address; +}; + +export type SetGatingProgramInstructionDataArgs = { newGatingProgram: Address }; + +export function getSetGatingProgramInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['newGatingProgram', getAddressEncoder()], + ]), + (value) => ({ ...value, discriminator: SET_GATING_PROGRAM_DISCRIMINATOR }) + ); +} + +export function getSetGatingProgramInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['newGatingProgram', getAddressDecoder()], + ]); +} + +export function getSetGatingProgramInstructionDataCodec(): Codec< + SetGatingProgramInstructionDataArgs, + SetGatingProgramInstructionData +> { + return combineCodec( + getSetGatingProgramInstructionDataEncoder(), + getSetGatingProgramInstructionDataDecoder() + ); +} + +export type SetGatingProgramInput< + TAccountAuthority extends string = string, + TAccountMintConfig extends string = string, +> = { + authority: TransactionSigner; + mintConfig: Address; + newGatingProgram: SetGatingProgramInstructionDataArgs['newGatingProgram']; +}; + +export function getSetGatingProgramInstruction< + TAccountAuthority extends string, + TAccountMintConfig extends string, + TProgramAddress extends Address = typeof EBALTS_PROGRAM_ADDRESS, +>( + input: SetGatingProgramInput, + config?: { programAddress?: TProgramAddress } +): SetGatingProgramInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMintConfig +> { + // Program address. + const programAddress = config?.programAddress ?? EBALTS_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: false }, + mintConfig: { value: input.mintConfig ?? null, isWritable: true }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.mintConfig), + ], + programAddress, + data: getSetGatingProgramInstructionDataEncoder().encode( + args as SetGatingProgramInstructionDataArgs + ), + } as SetGatingProgramInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMintConfig + >; + + return instruction; +} + +export type ParsedSetGatingProgramInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + mintConfig: TAccountMetas[1]; + }; + data: SetGatingProgramInstructionData; +}; + +export function parseSetGatingProgramInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedSetGatingProgramInstruction { + if (instruction.accounts.length < 2) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + mintConfig: getNextAccount(), + }, + data: getSetGatingProgramInstructionDataDecoder().decode(instruction.data), + }; +} diff --git a/packages/ebalts/src/generated/instructions/thaw.ts b/packages/ebalts/src/generated/instructions/thaw.ts new file mode 100644 index 0000000..be59827 --- /dev/null +++ b/packages/ebalts/src/generated/instructions/thaw.ts @@ -0,0 +1,225 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/kit'; +import { EBALTS_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const THAW_DISCRIMINATOR = 4; + +export function getThawDiscriminatorBytes() { + return getU8Encoder().encode(THAW_DISCRIMINATOR); +} + +export type ThawInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountAuthority extends string | IAccountMeta = string, + TAccountMint extends string | IAccountMeta = string, + TAccountTokenAccount extends string | IAccountMeta = string, + TAccountMintConfig extends string | IAccountMeta = string, + TAccountTokenProgram extends + | string + | IAccountMeta = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountAuthority extends string + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority, + TAccountMint extends string + ? ReadonlyAccount + : TAccountMint, + TAccountTokenAccount extends string + ? WritableAccount + : TAccountTokenAccount, + TAccountMintConfig extends string + ? ReadonlyAccount + : TAccountMintConfig, + TAccountTokenProgram extends string + ? ReadonlyAccount + : TAccountTokenProgram, + ...TRemainingAccounts, + ] + >; + +export type ThawInstructionData = { discriminator: number }; + +export type ThawInstructionDataArgs = {}; + +export function getThawInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([['discriminator', getU8Encoder()]]), + (value) => ({ ...value, discriminator: THAW_DISCRIMINATOR }) + ); +} + +export function getThawInstructionDataDecoder(): Decoder { + return getStructDecoder([['discriminator', getU8Decoder()]]); +} + +export function getThawInstructionDataCodec(): Codec< + ThawInstructionDataArgs, + ThawInstructionData +> { + return combineCodec( + getThawInstructionDataEncoder(), + getThawInstructionDataDecoder() + ); +} + +export type ThawInput< + TAccountAuthority extends string = string, + TAccountMint extends string = string, + TAccountTokenAccount extends string = string, + TAccountMintConfig extends string = string, + TAccountTokenProgram extends string = string, +> = { + authority: TransactionSigner; + mint: Address; + tokenAccount: Address; + mintConfig: Address; + tokenProgram?: Address; +}; + +export function getThawInstruction< + TAccountAuthority extends string, + TAccountMint extends string, + TAccountTokenAccount extends string, + TAccountMintConfig extends string, + TAccountTokenProgram extends string, + TProgramAddress extends Address = typeof EBALTS_PROGRAM_ADDRESS, +>( + input: ThawInput< + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountMintConfig, + TAccountTokenProgram + >, + config?: { programAddress?: TProgramAddress } +): ThawInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountMintConfig, + TAccountTokenProgram +> { + // Program address. + const programAddress = config?.programAddress ?? EBALTS_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: false }, + mint: { value: input.mint ?? null, isWritable: false }, + tokenAccount: { value: input.tokenAccount ?? null, isWritable: true }, + mintConfig: { value: input.mintConfig ?? null, isWritable: false }, + tokenProgram: { value: input.tokenProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Resolve default values. + if (!accounts.tokenProgram.value) { + accounts.tokenProgram.value = + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' as Address<'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.mint), + getAccountMeta(accounts.tokenAccount), + getAccountMeta(accounts.mintConfig), + getAccountMeta(accounts.tokenProgram), + ], + programAddress, + data: getThawInstructionDataEncoder().encode({}), + } as ThawInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountMintConfig, + TAccountTokenProgram + >; + + return instruction; +} + +export type ParsedThawInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + mint: TAccountMetas[1]; + tokenAccount: TAccountMetas[2]; + mintConfig: TAccountMetas[3]; + tokenProgram: TAccountMetas[4]; + }; + data: ThawInstructionData; +}; + +export function parseThawInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedThawInstruction { + if (instruction.accounts.length < 5) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + mint: getNextAccount(), + tokenAccount: getNextAccount(), + mintConfig: getNextAccount(), + tokenProgram: getNextAccount(), + }, + data: getThawInstructionDataDecoder().decode(instruction.data), + }; +} diff --git a/packages/ebalts/src/generated/instructions/thawPermissionless.ts b/packages/ebalts/src/generated/instructions/thawPermissionless.ts new file mode 100644 index 0000000..65820dd --- /dev/null +++ b/packages/ebalts/src/generated/instructions/thawPermissionless.ts @@ -0,0 +1,258 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/kit'; +import { EBALTS_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const THAW_PERMISSIONLESS_DISCRIMINATOR = 6; + +export function getThawPermissionlessDiscriminatorBytes() { + return getU8Encoder().encode(THAW_PERMISSIONLESS_DISCRIMINATOR); +} + +export type ThawPermissionlessInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountAuthority extends string | IAccountMeta = string, + TAccountMint extends string | IAccountMeta = string, + TAccountTokenAccount extends string | IAccountMeta = string, + TAccountTokenAccountOwner extends string | IAccountMeta = string, + TAccountMintConfig extends string | IAccountMeta = string, + TAccountTokenProgram extends + | string + | IAccountMeta = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + TAccountGatingProgram extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountAuthority extends string + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority, + TAccountMint extends string + ? ReadonlyAccount + : TAccountMint, + TAccountTokenAccount extends string + ? WritableAccount + : TAccountTokenAccount, + TAccountTokenAccountOwner extends string + ? ReadonlyAccount + : TAccountTokenAccountOwner, + TAccountMintConfig extends string + ? ReadonlyAccount + : TAccountMintConfig, + TAccountTokenProgram extends string + ? ReadonlyAccount + : TAccountTokenProgram, + TAccountGatingProgram extends string + ? ReadonlyAccount + : TAccountGatingProgram, + ...TRemainingAccounts, + ] + >; + +export type ThawPermissionlessInstructionData = { discriminator: number }; + +export type ThawPermissionlessInstructionDataArgs = {}; + +export function getThawPermissionlessInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([['discriminator', getU8Encoder()]]), + (value) => ({ ...value, discriminator: THAW_PERMISSIONLESS_DISCRIMINATOR }) + ); +} + +export function getThawPermissionlessInstructionDataDecoder(): Decoder { + return getStructDecoder([['discriminator', getU8Decoder()]]); +} + +export function getThawPermissionlessInstructionDataCodec(): Codec< + ThawPermissionlessInstructionDataArgs, + ThawPermissionlessInstructionData +> { + return combineCodec( + getThawPermissionlessInstructionDataEncoder(), + getThawPermissionlessInstructionDataDecoder() + ); +} + +export type ThawPermissionlessInput< + TAccountAuthority extends string = string, + TAccountMint extends string = string, + TAccountTokenAccount extends string = string, + TAccountTokenAccountOwner extends string = string, + TAccountMintConfig extends string = string, + TAccountTokenProgram extends string = string, + TAccountGatingProgram extends string = string, +> = { + authority: TransactionSigner; + mint: Address; + tokenAccount: Address; + tokenAccountOwner: Address; + mintConfig: Address; + tokenProgram?: Address; + gatingProgram: Address; +}; + +export function getThawPermissionlessInstruction< + TAccountAuthority extends string, + TAccountMint extends string, + TAccountTokenAccount extends string, + TAccountTokenAccountOwner extends string, + TAccountMintConfig extends string, + TAccountTokenProgram extends string, + TAccountGatingProgram extends string, + TProgramAddress extends Address = typeof EBALTS_PROGRAM_ADDRESS, +>( + input: ThawPermissionlessInput< + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountTokenAccountOwner, + TAccountMintConfig, + TAccountTokenProgram, + TAccountGatingProgram + >, + config?: { programAddress?: TProgramAddress } +): ThawPermissionlessInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountTokenAccountOwner, + TAccountMintConfig, + TAccountTokenProgram, + TAccountGatingProgram +> { + // Program address. + const programAddress = config?.programAddress ?? EBALTS_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: false }, + mint: { value: input.mint ?? null, isWritable: false }, + tokenAccount: { value: input.tokenAccount ?? null, isWritable: true }, + tokenAccountOwner: { + value: input.tokenAccountOwner ?? null, + isWritable: false, + }, + mintConfig: { value: input.mintConfig ?? null, isWritable: false }, + tokenProgram: { value: input.tokenProgram ?? null, isWritable: false }, + gatingProgram: { value: input.gatingProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Resolve default values. + if (!accounts.tokenProgram.value) { + accounts.tokenProgram.value = + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' as Address<'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.mint), + getAccountMeta(accounts.tokenAccount), + getAccountMeta(accounts.tokenAccountOwner), + getAccountMeta(accounts.mintConfig), + getAccountMeta(accounts.tokenProgram), + getAccountMeta(accounts.gatingProgram), + ], + programAddress, + data: getThawPermissionlessInstructionDataEncoder().encode({}), + } as ThawPermissionlessInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMint, + TAccountTokenAccount, + TAccountTokenAccountOwner, + TAccountMintConfig, + TAccountTokenProgram, + TAccountGatingProgram + >; + + return instruction; +} + +export type ParsedThawPermissionlessInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + mint: TAccountMetas[1]; + tokenAccount: TAccountMetas[2]; + tokenAccountOwner: TAccountMetas[3]; + mintConfig: TAccountMetas[4]; + tokenProgram: TAccountMetas[5]; + gatingProgram: TAccountMetas[6]; + }; + data: ThawPermissionlessInstructionData; +}; + +export function parseThawPermissionlessInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedThawPermissionlessInstruction { + if (instruction.accounts.length < 7) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + mint: getNextAccount(), + tokenAccount: getNextAccount(), + tokenAccountOwner: getNextAccount(), + mintConfig: getNextAccount(), + tokenProgram: getNextAccount(), + gatingProgram: getNextAccount(), + }, + data: getThawPermissionlessInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/packages/ebalts/src/generated/instructions/togglePermissionlessInstructions.ts b/packages/ebalts/src/generated/instructions/togglePermissionlessInstructions.ts new file mode 100644 index 0000000..1d1c278 --- /dev/null +++ b/packages/ebalts/src/generated/instructions/togglePermissionlessInstructions.ts @@ -0,0 +1,205 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getBooleanDecoder, + getBooleanEncoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/kit'; +import { EBALTS_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const TOGGLE_PERMISSIONLESS_INSTRUCTIONS_DISCRIMINATOR = 8; + +export function getTogglePermissionlessInstructionsDiscriminatorBytes() { + return getU8Encoder().encode( + TOGGLE_PERMISSIONLESS_INSTRUCTIONS_DISCRIMINATOR + ); +} + +export type TogglePermissionlessInstructionsInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountAuthority extends string | IAccountMeta = string, + TAccountMintConfig extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountAuthority extends string + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority, + TAccountMintConfig extends string + ? WritableAccount + : TAccountMintConfig, + ...TRemainingAccounts, + ] + >; + +export type TogglePermissionlessInstructionsInstructionData = { + discriminator: number; + freezeEnabled: boolean; + thawEnabled: boolean; +}; + +export type TogglePermissionlessInstructionsInstructionDataArgs = { + freezeEnabled: boolean; + thawEnabled: boolean; +}; + +export function getTogglePermissionlessInstructionsInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['freezeEnabled', getBooleanEncoder()], + ['thawEnabled', getBooleanEncoder()], + ]), + (value) => ({ + ...value, + discriminator: TOGGLE_PERMISSIONLESS_INSTRUCTIONS_DISCRIMINATOR, + }) + ); +} + +export function getTogglePermissionlessInstructionsInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['freezeEnabled', getBooleanDecoder()], + ['thawEnabled', getBooleanDecoder()], + ]); +} + +export function getTogglePermissionlessInstructionsInstructionDataCodec(): Codec< + TogglePermissionlessInstructionsInstructionDataArgs, + TogglePermissionlessInstructionsInstructionData +> { + return combineCodec( + getTogglePermissionlessInstructionsInstructionDataEncoder(), + getTogglePermissionlessInstructionsInstructionDataDecoder() + ); +} + +export type TogglePermissionlessInstructionsInput< + TAccountAuthority extends string = string, + TAccountMintConfig extends string = string, +> = { + authority: TransactionSigner; + mintConfig: Address; + freezeEnabled: TogglePermissionlessInstructionsInstructionDataArgs['freezeEnabled']; + thawEnabled: TogglePermissionlessInstructionsInstructionDataArgs['thawEnabled']; +}; + +export function getTogglePermissionlessInstructionsInstruction< + TAccountAuthority extends string, + TAccountMintConfig extends string, + TProgramAddress extends Address = typeof EBALTS_PROGRAM_ADDRESS, +>( + input: TogglePermissionlessInstructionsInput< + TAccountAuthority, + TAccountMintConfig + >, + config?: { programAddress?: TProgramAddress } +): TogglePermissionlessInstructionsInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMintConfig +> { + // Program address. + const programAddress = config?.programAddress ?? EBALTS_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + authority: { value: input.authority ?? null, isWritable: false }, + mintConfig: { value: input.mintConfig ?? null, isWritable: true }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.authority), + getAccountMeta(accounts.mintConfig), + ], + programAddress, + data: getTogglePermissionlessInstructionsInstructionDataEncoder().encode( + args as TogglePermissionlessInstructionsInstructionDataArgs + ), + } as TogglePermissionlessInstructionsInstruction< + TProgramAddress, + TAccountAuthority, + TAccountMintConfig + >; + + return instruction; +} + +export type ParsedTogglePermissionlessInstructionsInstruction< + TProgram extends string = typeof EBALTS_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + authority: TAccountMetas[0]; + mintConfig: TAccountMetas[1]; + }; + data: TogglePermissionlessInstructionsInstructionData; +}; + +export function parseTogglePermissionlessInstructionsInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedTogglePermissionlessInstructionsInstruction { + if (instruction.accounts.length < 2) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + authority: getNextAccount(), + mintConfig: getNextAccount(), + }, + data: getTogglePermissionlessInstructionsInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/packages/ebalts/src/generated/pdas/freezeExtraMetasAccount.ts b/packages/ebalts/src/generated/pdas/freezeExtraMetasAccount.ts new file mode 100644 index 0000000..b649528 --- /dev/null +++ b/packages/ebalts/src/generated/pdas/freezeExtraMetasAccount.ts @@ -0,0 +1,35 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + getAddressEncoder, + getProgramDerivedAddress, + getUtf8Encoder, + type Address, + type ProgramDerivedAddress, +} from '@solana/kit'; + +export type FreezeExtraMetasAccountSeeds = { + mint: Address; +}; + +export async function findFreezeExtraMetasAccountPda( + seeds: FreezeExtraMetasAccountSeeds, + config: { programAddress?: Address | undefined } = {} +): Promise { + const { + programAddress = 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, + } = config; + return await getProgramDerivedAddress({ + programAddress, + seeds: [ + getUtf8Encoder().encode('freeze_extra_account_metas'), + getAddressEncoder().encode(seeds.mint), + ], + }); +} diff --git a/packages/ebalts/src/generated/pdas/index.ts b/packages/ebalts/src/generated/pdas/index.ts new file mode 100644 index 0000000..11a9dc7 --- /dev/null +++ b/packages/ebalts/src/generated/pdas/index.ts @@ -0,0 +1,11 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './freezeExtraMetasAccount'; +export * from './mintConfig'; +export * from './thawExtraMetasAccount'; diff --git a/packages/ebalts/src/generated/pdas/mintConfig.ts b/packages/ebalts/src/generated/pdas/mintConfig.ts new file mode 100644 index 0000000..aca2a7c --- /dev/null +++ b/packages/ebalts/src/generated/pdas/mintConfig.ts @@ -0,0 +1,35 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + getAddressEncoder, + getProgramDerivedAddress, + getUtf8Encoder, + type Address, + type ProgramDerivedAddress, +} from '@solana/kit'; + +export type MintConfigSeeds = { + mint: Address; +}; + +export async function findMintConfigPda( + seeds: MintConfigSeeds, + config: { programAddress?: Address | undefined } = {} +): Promise { + const { + programAddress = 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, + } = config; + return await getProgramDerivedAddress({ + programAddress, + seeds: [ + getUtf8Encoder().encode('MINT_CONFIG'), + getAddressEncoder().encode(seeds.mint), + ], + }); +} diff --git a/packages/ebalts/src/generated/pdas/thawExtraMetasAccount.ts b/packages/ebalts/src/generated/pdas/thawExtraMetasAccount.ts new file mode 100644 index 0000000..cebe68f --- /dev/null +++ b/packages/ebalts/src/generated/pdas/thawExtraMetasAccount.ts @@ -0,0 +1,35 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + getAddressEncoder, + getProgramDerivedAddress, + getUtf8Encoder, + type Address, + type ProgramDerivedAddress, +} from '@solana/kit'; + +export type ThawExtraMetasAccountSeeds = { + mint: Address; +}; + +export async function findThawExtraMetasAccountPda( + seeds: ThawExtraMetasAccountSeeds, + config: { programAddress?: Address | undefined } = {} +): Promise { + const { + programAddress = 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, + } = config; + return await getProgramDerivedAddress({ + programAddress, + seeds: [ + getUtf8Encoder().encode('thaw_extra_account_metas'), + getAddressEncoder().encode(seeds.mint), + ], + }); +} diff --git a/packages/ebalts/src/generated/programs/ebalts.ts b/packages/ebalts/src/generated/programs/ebalts.ts new file mode 100644 index 0000000..f9ee55e --- /dev/null +++ b/packages/ebalts/src/generated/programs/ebalts.ts @@ -0,0 +1,123 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + containsBytes, + getU8Encoder, + type Address, + type ReadonlyUint8Array, +} from '@solana/kit'; +import { + type ParsedCreateConfigInstruction, + type ParsedForfeitFreezeAuthorityInstruction, + type ParsedFreezeInstruction, + type ParsedFreezePermissionlessInstruction, + type ParsedSetAuthorityInstruction, + type ParsedSetGatingProgramInstruction, + type ParsedThawInstruction, + type ParsedThawPermissionlessInstruction, + type ParsedTogglePermissionlessInstructionsInstruction, +} from '../instructions'; + +export const EBALTS_PROGRAM_ADDRESS = + 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>; + +export enum EbaltsAccount { + MintConfig, +} + +export function identifyEbaltsAccount( + account: { data: ReadonlyUint8Array } | ReadonlyUint8Array +): EbaltsAccount { + const data = 'data' in account ? account.data : account; + if (containsBytes(data, getU8Encoder().encode(1), 0)) { + return EbaltsAccount.MintConfig; + } + throw new Error( + 'The provided account could not be identified as a ebalts account.' + ); +} + +export enum EbaltsInstruction { + CreateConfig, + SetAuthority, + SetGatingProgram, + ForfeitFreezeAuthority, + Thaw, + Freeze, + ThawPermissionless, + FreezePermissionless, + TogglePermissionlessInstructions, +} + +export function identifyEbaltsInstruction( + instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array +): EbaltsInstruction { + const data = 'data' in instruction ? instruction.data : instruction; + if (containsBytes(data, getU8Encoder().encode(0), 0)) { + return EbaltsInstruction.CreateConfig; + } + if (containsBytes(data, getU8Encoder().encode(1), 0)) { + return EbaltsInstruction.SetAuthority; + } + if (containsBytes(data, getU8Encoder().encode(2), 0)) { + return EbaltsInstruction.SetGatingProgram; + } + if (containsBytes(data, getU8Encoder().encode(3), 0)) { + return EbaltsInstruction.ForfeitFreezeAuthority; + } + if (containsBytes(data, getU8Encoder().encode(4), 0)) { + return EbaltsInstruction.Thaw; + } + if (containsBytes(data, getU8Encoder().encode(5), 0)) { + return EbaltsInstruction.Freeze; + } + if (containsBytes(data, getU8Encoder().encode(6), 0)) { + return EbaltsInstruction.ThawPermissionless; + } + if (containsBytes(data, getU8Encoder().encode(7), 0)) { + return EbaltsInstruction.FreezePermissionless; + } + if (containsBytes(data, getU8Encoder().encode(8), 0)) { + return EbaltsInstruction.TogglePermissionlessInstructions; + } + throw new Error( + 'The provided instruction could not be identified as a ebalts instruction.' + ); +} + +export type ParsedEbaltsInstruction< + TProgram extends string = 'Eba1ts11111111111111111111111111111111111111', +> = + | ({ + instructionType: EbaltsInstruction.CreateConfig; + } & ParsedCreateConfigInstruction) + | ({ + instructionType: EbaltsInstruction.SetAuthority; + } & ParsedSetAuthorityInstruction) + | ({ + instructionType: EbaltsInstruction.SetGatingProgram; + } & ParsedSetGatingProgramInstruction) + | ({ + instructionType: EbaltsInstruction.ForfeitFreezeAuthority; + } & ParsedForfeitFreezeAuthorityInstruction) + | ({ + instructionType: EbaltsInstruction.Thaw; + } & ParsedThawInstruction) + | ({ + instructionType: EbaltsInstruction.Freeze; + } & ParsedFreezeInstruction) + | ({ + instructionType: EbaltsInstruction.ThawPermissionless; + } & ParsedThawPermissionlessInstruction) + | ({ + instructionType: EbaltsInstruction.FreezePermissionless; + } & ParsedFreezePermissionlessInstruction) + | ({ + instructionType: EbaltsInstruction.TogglePermissionlessInstructions; + } & ParsedTogglePermissionlessInstructionsInstruction); diff --git a/packages/ebalts/src/generated/programs/index.ts b/packages/ebalts/src/generated/programs/index.ts new file mode 100644 index 0000000..eec9ccf --- /dev/null +++ b/packages/ebalts/src/generated/programs/index.ts @@ -0,0 +1,9 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +export * from './ebalts'; diff --git a/packages/ebalts/src/generated/shared/index.ts b/packages/ebalts/src/generated/shared/index.ts new file mode 100644 index 0000000..7ba9053 --- /dev/null +++ b/packages/ebalts/src/generated/shared/index.ts @@ -0,0 +1,164 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + AccountRole, + isProgramDerivedAddress, + isTransactionSigner as kitIsTransactionSigner, + type Address, + type IAccountMeta, + type IAccountSignerMeta, + type ProgramDerivedAddress, + type TransactionSigner, + upgradeRoleToSigner, +} from '@solana/kit'; + +/** + * Asserts that the given value is not null or undefined. + * @internal + */ +export function expectSome(value: T | null | undefined): T { + if (value == null) { + throw new Error('Expected a value but received null or undefined.'); + } + return value; +} + +/** + * Asserts that the given value is a PublicKey. + * @internal + */ +export function expectAddress( + value: + | Address + | ProgramDerivedAddress + | TransactionSigner + | null + | undefined +): Address { + if (!value) { + throw new Error('Expected a Address.'); + } + if (typeof value === 'object' && 'address' in value) { + return value.address; + } + if (Array.isArray(value)) { + return value[0]; + } + return value as Address; +} + +/** + * Asserts that the given value is a PDA. + * @internal + */ +export function expectProgramDerivedAddress( + value: + | Address + | ProgramDerivedAddress + | TransactionSigner + | null + | undefined +): ProgramDerivedAddress { + if (!value || !Array.isArray(value) || !isProgramDerivedAddress(value)) { + throw new Error('Expected a ProgramDerivedAddress.'); + } + return value; +} + +/** + * Asserts that the given value is a TransactionSigner. + * @internal + */ +export function expectTransactionSigner( + value: + | Address + | ProgramDerivedAddress + | TransactionSigner + | null + | undefined +): TransactionSigner { + if (!value || !isTransactionSigner(value)) { + throw new Error('Expected a TransactionSigner.'); + } + return value; +} + +/** + * Defines an instruction account to resolve. + * @internal + */ +export type ResolvedAccount< + T extends string = string, + U extends + | Address + | ProgramDerivedAddress + | TransactionSigner + | null = + | Address + | ProgramDerivedAddress + | TransactionSigner + | null, +> = { + isWritable: boolean; + value: U; +}; + +/** + * Defines an instruction that stores additional bytes on-chain. + * @internal + */ +export type IInstructionWithByteDelta = { + byteDelta: number; +}; + +/** + * Get account metas and signers from resolved accounts. + * @internal + */ +export function getAccountMetaFactory( + programAddress: Address, + optionalAccountStrategy: 'omitted' | 'programId' +) { + return ( + account: ResolvedAccount + ): IAccountMeta | IAccountSignerMeta | undefined => { + if (!account.value) { + if (optionalAccountStrategy === 'omitted') return; + return Object.freeze({ + address: programAddress, + role: AccountRole.READONLY, + }); + } + + const writableRole = account.isWritable + ? AccountRole.WRITABLE + : AccountRole.READONLY; + return Object.freeze({ + address: expectAddress(account.value), + role: isTransactionSigner(account.value) + ? upgradeRoleToSigner(writableRole) + : writableRole, + ...(isTransactionSigner(account.value) ? { signer: account.value } : {}), + }); + }; +} + +export function isTransactionSigner( + value: + | Address + | ProgramDerivedAddress + | TransactionSigner +): value is TransactionSigner { + return ( + !!value && + typeof value === 'object' && + 'address' in value && + kitIsTransactionSigner(value) + ); +} diff --git a/packages/ebalts/src/index.ts b/packages/ebalts/src/index.ts new file mode 100644 index 0000000..f883596 --- /dev/null +++ b/packages/ebalts/src/index.ts @@ -0,0 +1,104 @@ +import { type Address, type Rpc, type GetAccountInfoApi, type Instruction, fetchEncodedAccount, type TransactionSigner, AccountRole, type AccountMeta, type MaybeEncodedAccount } from '@solana/kit'; +import { findMintConfigPda } from './generated/pdas/mintConfig'; +import { findFreezeExtraMetasAccountPda, findThawExtraMetasAccountPda, getFreezePermissionlessInstruction, getMintConfigDecoder, getThawPermissionlessInstruction } from './generated'; +import { resolveExtraMetas } from '@mosaic/tlv-account-resolution'; + +export * from './generated'; + +export async function createThawPermissionlessInstructionWithExtraMetas( + authority: TransactionSigner, + tokenAccount: Address, + mint: Address, + mintConfig: Address, + tokenAccountOwner: Address, + programAddress: Address, + accountRetriever: (address: Address) => Promise>, +): Promise { + + const mintConfigPda = await findMintConfigPda({ mint }, { programAddress }); + const mintConfigAccount = await accountRetriever(mintConfigPda[0]); + if (!mintConfigAccount.exists) { + throw new Error('Mint config account not found'); + } + const mintConfigData = getMintConfigDecoder().decode(mintConfigAccount.data); + + const thawExtraMetas = await findThawExtraMetasAccountPda({ mint }, { programAddress: mintConfigData.gatingProgram }); + + console.log(mintConfigData); + console.log(thawExtraMetas[0]); + + + const canThawPermissionlessInstruction = getCanThawPermissionlessAccountMetas(authority.address, tokenAccount, mint, tokenAccountOwner, thawExtraMetas[0]); + + const thawAccountInstruction = getThawPermissionlessInstruction({ + authority, + tokenAccount, + mint, + mintConfig, + tokenAccountOwner, + gatingProgram: mintConfigData.gatingProgram, + }, + { + programAddress + }); + + const metas = await resolveExtraMetas(accountRetriever, thawExtraMetas[0], canThawPermissionlessInstruction, Buffer.from(thawAccountInstruction.data), mintConfigData.gatingProgram); + + const ix = { + ...thawAccountInstruction, + accounts: [...thawAccountInstruction.accounts!, ...metas.slice(4)], + } + return ix; +} + +function getCanThawPermissionlessAccountMetas( + authority: Address, + tokenAccount: Address, + mint: Address, + owner: Address, + extraMetasThaw: Address, +): AccountMeta[] { + return [ + { address: authority, role: AccountRole.READONLY }, + { address: tokenAccount, role: AccountRole.READONLY }, + { address: mint, role: AccountRole.READONLY }, + { address: owner, role: AccountRole.READONLY }, + { address: extraMetasThaw, role: AccountRole.READONLY }, + ] +} + +export async function createFreezePermissionlessInstructionWithExtraMetas( + authority: TransactionSigner, + tokenAccount: Address, + mint: Address, + mintConfig: Address, + tokenAccountOwner: Address, + accountRetriever: (address: Address) => Promise>, +): Promise { + + const mintConfigPda = await findMintConfigPda({ mint }); + const mintConfigAccount = await accountRetriever(mintConfigPda[0]); + if (!mintConfigAccount.exists) { + throw new Error('Mint config account not found'); + } + const mintConfigData = getMintConfigDecoder().decode(mintConfigAccount.data); + + const freezeExtraMetas = await findFreezeExtraMetasAccountPda({ mint }, { programAddress: mintConfigData.gatingProgram }); + + const freezeAccountInstruction = getFreezePermissionlessInstruction({ + authority, + tokenAccount, + mint, + mintConfig, + tokenAccountOwner, + gatingProgram: mintConfigData.gatingProgram, + }); + + const metas = await resolveExtraMetas(accountRetriever, freezeExtraMetas[0], freezeAccountInstruction.accounts, Buffer.from(freezeAccountInstruction.data), mintConfigData.gatingProgram); + + const ix = { + ...freezeAccountInstruction, + accounts: metas, + } + return ix; +} \ No newline at end of file diff --git a/packages/ebalts/tsconfig.json b/packages/ebalts/tsconfig.json new file mode 100644 index 0000000..01db065 --- /dev/null +++ b/packages/ebalts/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"], + "types": ["jest", "node"] +} diff --git a/packages/sdk/package.json b/packages/sdk/package.json index f4743a3..129f7a7 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -26,7 +26,10 @@ "clean": "rm -rf dist" }, "dependencies": { - "gill": "^0.10.2" + "gill": "^0.10.2", + "@mosaic/tlv-account-resolution": "workspace:*", + "@mosaic/ebalts": "workspace:*", + "@mosaic/abl": "workspace:*" }, "devDependencies": { "@types/jest": "^29.5.0", diff --git a/packages/sdk/src/abl/createList.ts b/packages/sdk/src/abl/createList.ts new file mode 100644 index 0000000..25791a8 --- /dev/null +++ b/packages/sdk/src/abl/createList.ts @@ -0,0 +1,51 @@ +import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { ABL_PROGRAM_ID } from "./utils"; +import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; + + +export const getCreateListInstructions = async (input: { + authority: TransactionSigner; + }): Promise<{instructions: Instruction[], listConfig: Address}> => { + const seed = await generateKeyPairSigner(); + + const listConfigPda = await findListConfigPda({ authority: input.authority.address, seed: seed.address }, { programAddress: ABL_PROGRAM_ID }); + + + const createListInstruction = getInitializeListConfigInstruction({ + authority: input.authority, + listConfig: listConfigPda[0], + mode: Mode.AllowWithPermissionlessEOAs, + seed: seed.address, + }, + { programAddress: ABL_PROGRAM_ID }); + + return { + instructions: [createListInstruction], + listConfig: listConfigPda[0], + }; +} + +export const getCreateListTransaction = async (input: { + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + }): Promise<{ + transaction: FullTransaction< + TransactionVersion, + TransactionMessageWithFeePayer, + TransactionWithBlockhashLifetime>, + listConfig: Address}> => { + + const {instructions, listConfig} = await getCreateListInstructions(input); + const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return { + transaction, + listConfig, + }; +} \ No newline at end of file diff --git a/packages/sdk/src/abl/index.ts b/packages/sdk/src/abl/index.ts new file mode 100644 index 0000000..47f3140 --- /dev/null +++ b/packages/sdk/src/abl/index.ts @@ -0,0 +1,3 @@ +export * from './createList'; +export * from './utils'; +export * from './setExtraMetas'; \ No newline at end of file diff --git a/packages/sdk/src/abl/setExtraMetas.ts b/packages/sdk/src/abl/setExtraMetas.ts new file mode 100644 index 0000000..7ccf1c2 --- /dev/null +++ b/packages/sdk/src/abl/setExtraMetas.ts @@ -0,0 +1,50 @@ +import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { ABL_PROGRAM_ID } from "./utils"; +import { getSetExtraMetasThawInstruction } from '@mosaic/abl'; +import { findMintConfigPda, findThawExtraMetasAccountPda } from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from "../ebalts"; + + +export const getSetExtraMetasInstructions = async (input: { + authority: TransactionSigner; + mint: Address; + list: Address; + }): Promise[]> => { + + const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); + const extraMetasThaw = await findThawExtraMetasAccountPda({ mint: input.mint }, { programAddress: ABL_PROGRAM_ID }); + + + const createListInstruction = getSetExtraMetasThawInstruction({ + authority: input.authority, + listConfig: input.list, + mint: input.mint, + ebaltsMintConfig: mintConfigPda[0], + extraMetasThaw: extraMetasThaw[0], + }, + { programAddress: ABL_PROGRAM_ID }); + + return [createListInstruction]; +} + +export const getSetExtraMetasTransaction = async (input: { + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; + list: Address; + }): Promise> => { + + const instructions = await getSetExtraMetasInstructions(input); + const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return transaction; +} \ No newline at end of file diff --git a/packages/sdk/src/abl/utils.ts b/packages/sdk/src/abl/utils.ts new file mode 100644 index 0000000..be68de0 --- /dev/null +++ b/packages/sdk/src/abl/utils.ts @@ -0,0 +1,4 @@ +import type { Address } from "gill"; + + +export const ABL_PROGRAM_ID = '8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N' as Address; \ No newline at end of file diff --git a/packages/sdk/src/ebalts/createConfig.ts b/packages/sdk/src/ebalts/createConfig.ts new file mode 100644 index 0000000..8affa72 --- /dev/null +++ b/packages/sdk/src/ebalts/createConfig.ts @@ -0,0 +1,56 @@ +import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; +import { ABL_PROGRAM_ID, getCreateListInstructions } from "../abl"; +import { findMintConfigPda, getCreateConfigInstruction } from "@mosaic/ebalts"; +import { EBALTS_PROGRAM_ID } from "./utils"; + + +export const getCreateConfigInstructions = async (input: { + authority: TransactionSigner; + mint: Address; + gatingProgram: Address; + }): Promise<{instructions: Instruction[], mintConfig: Address}> => { + + const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); + + const createConfigInstruction = getCreateConfigInstruction({ + payer: input.authority.address, + authority: input.authority, + mint: input.mint, + mintConfig: mintConfigPda[0], + gatingProgram: input.gatingProgram, + }, + { programAddress: EBALTS_PROGRAM_ID }); + + return { + instructions: [createConfigInstruction], + mintConfig: mintConfigPda[0], + }; +} + +export const getCreateConfigTransaction = async (input: { + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; + gatingProgram: Address; + }): Promise<{ + transaction: FullTransaction< + TransactionVersion, + TransactionMessageWithFeePayer, + TransactionWithBlockhashLifetime>, + mintConfig: Address}> => { + + const {instructions, mintConfig} = await getCreateConfigInstructions(input); + const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return { + transaction, + mintConfig, + }; +} \ No newline at end of file diff --git a/packages/sdk/src/ebalts/enablePermissionlessThaw.ts b/packages/sdk/src/ebalts/enablePermissionlessThaw.ts new file mode 100644 index 0000000..1f4f138 --- /dev/null +++ b/packages/sdk/src/ebalts/enablePermissionlessThaw.ts @@ -0,0 +1,45 @@ +import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; +import { ABL_PROGRAM_ID, getCreateListInstructions } from "../abl"; +import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction, getTogglePermissionlessInstructionsInstruction } from "@mosaic/ebalts"; +import { EBALTS_PROGRAM_ID } from "./utils"; + + +export const getEnablePermissionlessThawInstructions = async (input: { + authority: TransactionSigner; + mint: Address; + }): Promise[]> => { + + const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); + + const enablePermissionlessThawInstruction = getTogglePermissionlessInstructionsInstruction({ + authority: input.authority, + mintConfig: mintConfigPda[0], + thawEnabled: true, + freezeEnabled: false, + }, + { programAddress: EBALTS_PROGRAM_ID }); + + return [enablePermissionlessThawInstruction]; +} + +export const getEnablePermissionlessThawTransaction = async (input: { + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; + }): Promise> => { + + const instructions = await getEnablePermissionlessThawInstructions(input); + const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return transaction; +} \ No newline at end of file diff --git a/packages/sdk/src/ebalts/index.ts b/packages/sdk/src/ebalts/index.ts new file mode 100644 index 0000000..4797d64 --- /dev/null +++ b/packages/sdk/src/ebalts/index.ts @@ -0,0 +1,7 @@ + + +export * from './utils'; +export * from './createConfig'; +export * from './setGatingProgram'; +export * from './enablePermissionlessThaw'; +export * from './thawPermissionless'; \ No newline at end of file diff --git a/packages/sdk/src/ebalts/setGatingProgram.ts b/packages/sdk/src/ebalts/setGatingProgram.ts new file mode 100644 index 0000000..a44d337 --- /dev/null +++ b/packages/sdk/src/ebalts/setGatingProgram.ts @@ -0,0 +1,47 @@ +import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; +import { ABL_PROGRAM_ID, getCreateListInstructions } from "../abl"; +import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction } from "@mosaic/ebalts"; +import { EBALTS_PROGRAM_ID } from "./utils"; + + +export const getSetGatingProgramInstructions = async (input: { + authority: TransactionSigner; + mint: Address; + gatingProgram: Address; + }): Promise[]> => { + + const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); + const gatingProgram = (input.gatingProgram || '11111111111111111111111111111111') as Address; + + const setGatingProgramInstruction = getSetGatingProgramInstruction({ + authority: input.authority, + mintConfig: mintConfigPda[0], + newGatingProgram: gatingProgram, + }, + { programAddress: EBALTS_PROGRAM_ID }); + + return [setGatingProgramInstruction]; +} + +export const getSetGatingProgramTransaction = async (input: { + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; + gatingProgram: Address; + }): Promise> => { + + const instructions = await getSetGatingProgramInstructions(input); + const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return transaction; +} \ No newline at end of file diff --git a/packages/sdk/src/ebalts/thawPermissionless.ts b/packages/sdk/src/ebalts/thawPermissionless.ts new file mode 100644 index 0000000..a2c74ff --- /dev/null +++ b/packages/sdk/src/ebalts/thawPermissionless.ts @@ -0,0 +1,72 @@ +import { createTransaction, fetchEncodedAccount, generateKeyPairSigner, lamports, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; +import { ABL_PROGRAM_ID, getCreateListInstructions } from "../abl"; +import { createThawPermissionlessInstructionWithExtraMetas, findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction } from "@mosaic/ebalts"; +import { EBALTS_PROGRAM_ID } from "./utils"; +import { getTokenEncoder, AccountState, TOKEN_2022_PROGRAM_ADDRESS, AuthorityType } from "gill/programs"; + + +export const getThawPermissionlessInstructions = async (input: { + rpc: Rpc; + authority: TransactionSigner; + mint: Address; + tokenAccount: Address; + tokenAccountOwner: Address; + }): Promise[]> => { + + const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); + + const thawPermissionlessInstruction = await createThawPermissionlessInstructionWithExtraMetas(input.authority, input.tokenAccount, input.mint, mintConfigPda[0], input.tokenAccountOwner, EBALTS_PROGRAM_ID, + async (address: Address) => { + let data = getTokenEncoder().encode({ + amount: 0, + closeAuthority: null, + delegate: null, + delegatedAmount: 0, + extensions: null, + isNative: null, + mint: input.mint, + owner: input.tokenAccountOwner, + state: AccountState.Frozen + }); + + if (address === input.tokenAccount) { + return { + exists: true, + address, + data: new Uint8Array(data), + executable: false, + lamports: lamports(BigInt(2157600)), + programAddress: TOKEN_2022_PROGRAM_ADDRESS, + space: BigInt(data.byteLength), + } + } + return await fetchEncodedAccount(input.rpc, address) + } + ); + + return [thawPermissionlessInstruction]; +} + +export const getThawPermissionlessTransaction = async (input: { + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; + tokenAccount: Address; + tokenAccountOwner: Address; + }): Promise> => { + + const instructions = await getThawPermissionlessInstructions(input); + const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return transaction; +} \ No newline at end of file diff --git a/packages/sdk/src/ebalts/utils.ts b/packages/sdk/src/ebalts/utils.ts new file mode 100644 index 0000000..9cdcc46 --- /dev/null +++ b/packages/sdk/src/ebalts/utils.ts @@ -0,0 +1,4 @@ +import type { Address } from "gill"; + + +export const EBALTS_PROGRAM_ID = '81H44JYqk1p8RUks7pNJjhQG4Pj8FcaJeTUxZKN3JfLc' as Address; \ No newline at end of file diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index a5e5a60..4135c33 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -4,3 +4,5 @@ export * from './management/mint'; export * from './management/freeze'; export * from './management/force-transfer'; export * from './transactionUtil'; +export * from './abl'; +export * from './ebalts'; \ No newline at end of file diff --git a/packages/sdk/src/issuance/createMint.ts b/packages/sdk/src/issuance/createMint.ts index e452ea9..94a18c0 100644 --- a/packages/sdk/src/issuance/createMint.ts +++ b/packages/sdk/src/issuance/createMint.ts @@ -76,7 +76,7 @@ export class Token { const defaultAccountStateExtension = extension('DefaultAccountState', { state: initialState ? AccountState.Initialized - : AccountState.Uninitialized, + : AccountState.Frozen, }); this.extensions.push(defaultAccountStateExtension); return this; diff --git a/packages/sdk/src/templates/arcadeToken.ts b/packages/sdk/src/templates/arcadeToken.ts index 36cc597..b0c2dfc 100644 --- a/packages/sdk/src/templates/arcadeToken.ts +++ b/packages/sdk/src/templates/arcadeToken.ts @@ -68,7 +68,7 @@ export const createArcadeTokenInitTransaction = async ( additionalMetadata: new Map(), }) .withPausable(pausableAuthority || mintAuthority) - .withDefaultAccountState(true) + .withDefaultAccountState(false) .withConfidentialBalances(confidentialBalancesAuthority || mintAuthority) .withPermanentDelegate(permanentDelegateAuthority || mintAuthority) .buildTransaction({ diff --git a/packages/tlv-account-resolution/README.md b/packages/tlv-account-resolution/README.md new file mode 100644 index 0000000..e69de29 diff --git a/packages/tlv-account-resolution/jest.config.js b/packages/tlv-account-resolution/jest.config.js new file mode 100644 index 0000000..38e2b68 --- /dev/null +++ b/packages/tlv-account-resolution/jest.config.js @@ -0,0 +1,29 @@ +/** @type {import('jest').Config} */ +export default { + preset: 'ts-jest/presets/default-esm', + extensionsToTreatAsEsm: ['.ts'], + testEnvironment: 'node', + roots: ['/src'], + testMatch: ['**/__tests__/**/*.test.ts', '**/?(*.)+(spec|test).ts'], + transform: { + '^.+\\.ts$': [ + 'ts-jest', + { + useESM: true, + }, + ], + }, + collectCoverageFrom: [ + 'src/**/*.ts', + '!src/**/*.d.ts', + '!src/**/__tests__/**/*.test.ts', + '!src/**/*.test.ts', + '!src/**/__tests__/setup.ts', + '!src/**/__tests__/test-utils.ts', + ], + moduleNameMapper: { + '^@/(.*)$': '/src/$1', + }, + moduleFileExtensions: ['ts', 'js', 'json'], + setupFilesAfterEnv: ['/src/__tests__/setup.ts'], +}; diff --git a/packages/tlv-account-resolution/package.json b/packages/tlv-account-resolution/package.json new file mode 100644 index 0000000..8709241 --- /dev/null +++ b/packages/tlv-account-resolution/package.json @@ -0,0 +1,50 @@ +{ + "name": "@mosaic/tlv-account-resolution", + "version": "0.1.0", + "description": "SDK for Mosaic with helper functions for issuance and management of any token", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsc", + "dev": "echo 'Dev will be implemented'", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "lint": "eslint src --ext .ts", + "lint:fix": "eslint src --ext .ts --fix", + "type-check": "tsc --noEmit", + "clean": "rm -rf dist" + }, + "dependencies": { + "gill": "^0.10.2", + "@solana/kit": "2.3.0" + }, + "devDependencies": { + "@types/jest": "^29.5.0", + "@typescript-eslint/eslint-plugin": "^8.34.0", + "@typescript-eslint/parser": "^8.34.0", + "eslint": "^9.32.0", + "jest": "^29.5.0", + "ts-jest": "^29.1.0" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "keywords": [ + "solana", + "token-2022", + "extensions", + "core", + "hooks" + ] +} diff --git a/packages/tlv-account-resolution/src/errors.ts b/packages/tlv-account-resolution/src/errors.ts new file mode 100644 index 0000000..b404749 --- /dev/null +++ b/packages/tlv-account-resolution/src/errors.ts @@ -0,0 +1,96 @@ +/** Base class for errors */ +export abstract class TokenError extends Error { + constructor(message?: string) { + super(message); + } +} + +/** Thrown if an account is not found at the expected address */ +export class TokenAccountNotFoundError extends TokenError { + name = 'TokenAccountNotFoundError'; +} + +/** Thrown if a program state account is not a valid Account */ +export class TokenInvalidAccountError extends TokenError { + name = 'TokenInvalidAccountError'; +} + +/** Thrown if a program state account does not contain valid data */ +export class TokenInvalidAccountDataError extends TokenError { + name = 'TokenInvalidAccountDataError'; +} + +/** Thrown if a program state account is not owned by the expected token program */ +export class TokenInvalidAccountOwnerError extends TokenError { + name = 'TokenInvalidAccountOwnerError'; +} + +/** Thrown if the byte length of an program state account doesn't match the expected size */ +export class TokenInvalidAccountSizeError extends TokenError { + name = 'TokenInvalidAccountSizeError'; +} + +/** Thrown if the mint of a token account doesn't match the expected mint */ +export class TokenInvalidMintError extends TokenError { + name = 'TokenInvalidMintError'; +} + +/** Thrown if the owner of a token account doesn't match the expected owner */ +export class TokenInvalidOwnerError extends TokenError { + name = 'TokenInvalidOwnerError'; +} + +/** Thrown if the owner of a token account is a PDA (Program Derived Address) */ +export class TokenOwnerOffCurveError extends TokenError { + name = 'TokenOwnerOffCurveError'; +} + +/** Thrown if an instruction's program is invalid */ +export class TokenInvalidInstructionProgramError extends TokenError { + name = 'TokenInvalidInstructionProgramError'; +} + +/** Thrown if an instruction's keys are invalid */ +export class TokenInvalidInstructionKeysError extends TokenError { + name = 'TokenInvalidInstructionKeysError'; +} + +/** Thrown if an instruction's data is invalid */ +export class TokenInvalidInstructionDataError extends TokenError { + name = 'TokenInvalidInstructionDataError'; +} + +/** Thrown if an instruction's type is invalid */ +export class TokenInvalidInstructionTypeError extends TokenError { + name = 'TokenInvalidInstructionTypeError'; +} + +/** Thrown if the program does not support the desired instruction */ +export class TokenUnsupportedInstructionError extends TokenError { + name = 'TokenUnsupportedInstructionError'; +} + +/** Thrown if the transfer hook extra accounts contains an invalid account index */ +export class TokenTransferHookAccountNotFound extends TokenError { + name = 'TokenTransferHookAccountNotFound'; +} + +/** Thrown if the transfer hook extra accounts contains an invalid seed */ +export class TokenTransferHookInvalidSeed extends TokenError { + name = 'TokenTransferHookInvalidSeed'; +} + +/** Thrown if account data required by an extra account meta seed config could not be fetched */ +export class TokenTransferHookAccountDataNotFound extends TokenError { + name = 'TokenTransferHookAccountDataNotFound'; +} + +/** Thrown if pubkey data extra accounts config is invalid */ +export class TokenTransferHookInvalidPubkeyData extends TokenError { + name = 'TokenTransferHookInvalidPubkeyData'; +} + +/** Thrown if pubkey data source is too small for a pubkey */ +export class TokenTransferHookPubkeyDataTooSmall extends TokenError { + name = 'TokenTransferHookPubkeyDataTooSmall'; +} diff --git a/packages/tlv-account-resolution/src/index.ts b/packages/tlv-account-resolution/src/index.ts new file mode 100644 index 0000000..6837096 --- /dev/null +++ b/packages/tlv-account-resolution/src/index.ts @@ -0,0 +1,4 @@ +export * from './state'; +export * from './seeds'; +export * from './pubkeyData'; +export * from './errors'; \ No newline at end of file diff --git a/packages/tlv-account-resolution/src/pubkeyData.ts b/packages/tlv-account-resolution/src/pubkeyData.ts new file mode 100644 index 0000000..ca98083 --- /dev/null +++ b/packages/tlv-account-resolution/src/pubkeyData.ts @@ -0,0 +1,63 @@ + +import { + TokenTransferHookAccountDataNotFound, + TokenTransferHookInvalidPubkeyData, + TokenTransferHookPubkeyDataTooSmall, + TokenTransferHookAccountNotFound, +} from './errors.js'; +import { type Address, type Rpc, type AccountMeta, fetchEncodedAccount, type GetAccountInfoApi, address, getAddressDecoder, type MaybeEncodedAccount } from '@solana/kit'; + + +export async function unpackPubkeyData( + keyDataConfig: Uint8Array, + previousMetas: AccountMeta[], + instructionData: Buffer, + accountRetriever: (address: Address) => Promise>, +): Promise
{ + const [discriminator, ...rest] = keyDataConfig; + const remaining = new Uint8Array(rest); + switch (discriminator) { + case 1: + return unpackPubkeyDataFromInstructionData(remaining, instructionData); + case 2: + return unpackPubkeyDataFromAccountData(remaining, previousMetas, accountRetriever); + default: + throw new TokenTransferHookInvalidPubkeyData(); + } +} + +function unpackPubkeyDataFromInstructionData(remaining: Uint8Array, instructionData: Buffer): Address { + if (remaining.length < 1) { + throw new TokenTransferHookInvalidPubkeyData(); + } + const dataIndex = remaining[0]; + if (instructionData.length < dataIndex + 32) { + throw new TokenTransferHookPubkeyDataTooSmall(); + } + return getAddressDecoder().decode(instructionData, dataIndex); + //return new PublicKey(instructionData.subarray(dataIndex, dataIndex + PUBLIC_KEY_LENGTH)); +} + +async function unpackPubkeyDataFromAccountData( + remaining: Uint8Array, + previousMetas: AccountMeta[], + accountRetriever: (address: Address) => Promise>, +): Promise
{ + if (remaining.length < 2) { + throw new TokenTransferHookInvalidPubkeyData(); + } + const [accountIndex, dataIndex] = remaining; + if (previousMetas.length <= accountIndex) { + throw new TokenTransferHookAccountDataNotFound(); + } + const accountInfo = await accountRetriever(previousMetas[accountIndex].address); + //const accountInfo = await connection.getAccountInfo(); + if (!accountInfo.exists) { + throw new TokenTransferHookAccountNotFound(); + } + if (accountInfo.data.length < dataIndex + 32) { + throw new TokenTransferHookPubkeyDataTooSmall(); + } + return getAddressDecoder().decode(accountInfo.data, dataIndex); + //return new PublicKey(accountInfo.data.subarray(dataIndex, dataIndex + PUBLIC_KEY_LENGTH)); +} diff --git a/packages/tlv-account-resolution/src/seeds.ts b/packages/tlv-account-resolution/src/seeds.ts new file mode 100644 index 0000000..01711b1 --- /dev/null +++ b/packages/tlv-account-resolution/src/seeds.ts @@ -0,0 +1,134 @@ + +import { + TokenTransferHookAccountDataNotFound, + TokenTransferHookInvalidPubkeyData, + TokenTransferHookPubkeyDataTooSmall, + TokenTransferHookAccountNotFound, + TokenTransferHookInvalidSeed, +} from './errors.js'; +import { type Address, type Rpc, type AccountMeta, fetchEncodedAccount, type GetAccountInfoApi, address, getAddressDecoder, getAddressEncoder, type MaybeEncodedAccount } from '@solana/kit'; + +interface Seed { + data: Buffer; + packedLength: number; +} + +const DISCRIMINATOR_SPAN = 1; +const LITERAL_LENGTH_SPAN = 1; +const INSTRUCTION_ARG_OFFSET_SPAN = 1; +const INSTRUCTION_ARG_LENGTH_SPAN = 1; +const ACCOUNT_KEY_INDEX_SPAN = 1; +const ACCOUNT_DATA_ACCOUNT_INDEX_SPAN = 1; +const ACCOUNT_DATA_OFFSET_SPAN = 1; +const ACCOUNT_DATA_LENGTH_SPAN = 1; + +function unpackSeedLiteral(seeds: Uint8Array): Seed { + if (seeds.length < 1) { + throw new TokenTransferHookInvalidSeed(); + } + const [length, ...rest] = seeds; + if (rest.length < length) { + throw new TokenTransferHookInvalidSeed(); + } + return { + data: Buffer.from(rest.slice(0, length)), + packedLength: DISCRIMINATOR_SPAN + LITERAL_LENGTH_SPAN + length, + }; +} + +function unpackSeedInstructionArg(seeds: Uint8Array, instructionData: Buffer): Seed { + if (seeds.length < 2) { + throw new TokenTransferHookInvalidSeed(); + } + const [index, length] = seeds; + if (instructionData.length < length + index) { + throw new TokenTransferHookInvalidSeed(); + } + return { + data: instructionData.subarray(index, index + length), + packedLength: DISCRIMINATOR_SPAN + INSTRUCTION_ARG_OFFSET_SPAN + INSTRUCTION_ARG_LENGTH_SPAN, + }; +} + +function unpackSeedAccountKey(seeds: Uint8Array, previousMetas: AccountMeta[]): Seed { + if (seeds.length < 1) { + throw new TokenTransferHookInvalidSeed(); + } + const [index] = seeds; + if (previousMetas.length <= index) { + throw new TokenTransferHookInvalidSeed(); + } + return { + data: Buffer.from(getAddressEncoder().encode(previousMetas[index].address)), + packedLength: DISCRIMINATOR_SPAN + ACCOUNT_KEY_INDEX_SPAN, + }; +} + +async function unpackSeedAccountData( + seeds: Uint8Array, + previousMetas: AccountMeta[], + accountRetriever: (address: Address) => Promise>, +): Promise { + if (seeds.length < 3) { + throw new TokenTransferHookInvalidSeed(); + } + const [accountIndex, dataIndex, length] = seeds; + if (previousMetas.length <= accountIndex) { + throw new TokenTransferHookInvalidSeed(); + } + const accountInfo = await accountRetriever(previousMetas[accountIndex].address); + if (!accountInfo.exists) { + throw new TokenTransferHookAccountDataNotFound(); + } + if (accountInfo.data.length < dataIndex + length) { + throw new TokenTransferHookInvalidSeed(); + } + return { + data: Buffer.from(accountInfo.data.subarray(dataIndex, dataIndex + length)), + packedLength: + DISCRIMINATOR_SPAN + ACCOUNT_DATA_ACCOUNT_INDEX_SPAN + ACCOUNT_DATA_OFFSET_SPAN + ACCOUNT_DATA_LENGTH_SPAN, + }; +} + +async function unpackFirstSeed( + seeds: Uint8Array, + previousMetas: AccountMeta[], + instructionData: Buffer, + accountRetriever: (address: Address) => Promise>, +): Promise { + const [discriminator, ...rest] = seeds; + const remaining = new Uint8Array(rest); + switch (discriminator) { + case 0: + return null; + case 1: + return unpackSeedLiteral(remaining); + case 2: + return unpackSeedInstructionArg(remaining, instructionData); + case 3: + return unpackSeedAccountKey(remaining, previousMetas); + case 4: + return unpackSeedAccountData(remaining, previousMetas, accountRetriever); + default: + throw new TokenTransferHookInvalidSeed(); + } +} + +export async function unpackSeeds( + seeds: Uint8Array, + previousMetas: AccountMeta[], + instructionData: Buffer, + accountRetriever: (address: Address) => Promise>, +): Promise { + const unpackedSeeds: Buffer[] = []; + let i = 0; + while (i < 32) { + const seed = await unpackFirstSeed(seeds.slice(i), previousMetas, instructionData, accountRetriever); + if (seed == null) { + break; + } + unpackedSeeds.push(seed.data); + i += seed.packedLength; + } + return unpackedSeeds; +} diff --git a/packages/tlv-account-resolution/src/state.ts b/packages/tlv-account-resolution/src/state.ts new file mode 100644 index 0000000..2454143 --- /dev/null +++ b/packages/tlv-account-resolution/src/state.ts @@ -0,0 +1,147 @@ + +import { TokenTransferHookAccountNotFound, TokenTransferHookInvalidPubkeyData } from './errors.js'; +import { unpackSeeds } from './seeds.js'; +import { unpackPubkeyData } from './pubkeyData.js'; +import { type Address, type AccountMeta, type GetAccountInfoApi, type Rpc, getProgramDerivedAddress, address, AccountRole, mergeRoles, getAddressDecoder, type MaybeEncodedAccount } from '@solana/kit'; + + +export async function resolveExtraMetas( + accountRetriever: (address: Address) => Promise>, + extraMetasAddress: Address, + previousMetas: AccountMeta[], + instructionData: Buffer, + programId: Address, +): Promise { + const account = await accountRetriever(extraMetasAddress); + const extraAccountMetas = getExtraAccountMetas(account); + const resolvedMetas = [...previousMetas]; + for (const extraAccountMeta of extraAccountMetas) { + const resolvedMeta = await resolveExtraAccountMeta(accountRetriever, extraAccountMeta, resolvedMetas, instructionData, programId); + console.log("resolvedMeta", resolvedMeta); + resolvedMetas.push(resolvedMeta); + } + return resolvedMetas; +} + +/** ExtraAccountMeta as stored by the transfer hook program */ +export interface ExtraAccountMeta { + discriminator: number; + addressConfig: Uint8Array; + isSigner: boolean; + isWritable: boolean; +} + +export interface ExtraAccountMetaList { + count: number; + extraAccounts: ExtraAccountMeta[]; +} + + +/** Buffer layout for de/serializing a list of ExtraAccountMetaAccountData prefixed by a u32 length */ +export interface ExtraAccountMetaAccountData { + instructionDiscriminator: bigint; + length: number; + extraAccountsList: ExtraAccountMetaList; +} + + +/** Unpack an extra account metas account and parse the data into a list of ExtraAccountMetas */ +export function getExtraAccountMetas(account: MaybeEncodedAccount): ExtraAccountMeta[] { + if (!account.exists) { + throw new TokenTransferHookAccountNotFound(); + } + return unpackExtraAccountMetas(account.data); +} + +export function unpackExtraAccountMetas( + data: Uint8Array, +): ExtraAccountMeta[] { + if (data.length < 12) { + throw new TokenTransferHookInvalidPubkeyData(); + } + const discriminator = data.slice(0,8); + const length = new DataView(data.buffer, 8, 4).getUint32(0, true); + const count = new DataView(data.buffer, 12, 4).getUint32(0, true); + const offset = 16; + + console.log(length, count); + + if (length !== count * 35 + 4) { + throw new TokenTransferHookInvalidPubkeyData(); + } + + if (count * 35 > data.length - offset) { + throw new TokenTransferHookInvalidPubkeyData(); + } + + const extraAccounts = []; + for (let i = 0; i < count; i++) { + const extraAccount = data.slice(offset + i * 35, offset + (i + 1) * 35); + extraAccounts.push(unpackExtraAccountMeta(extraAccount)); + } + + return extraAccounts; +} + +export function unpackExtraAccountMeta(data: Uint8Array): ExtraAccountMeta { + const discriminator = data[0]; + const addressConfig = data.slice(1,33); + const isSigner = data[33] === 1; + const isWritable = data[34] === 1; + return { discriminator, addressConfig, isSigner, isWritable }; +} + +/** Take an ExtraAccountMeta and construct that into an actual AccountMeta */ +export async function resolveExtraAccountMeta( + accountRetriever: (address: Address) => Promise>, + extraMeta: ExtraAccountMeta, + previousMetas: AccountMeta[], + instructionData: Buffer, + programId: Address, +): Promise { + if (extraMeta.discriminator === 0) { + return { + address: getAddressDecoder().decode(extraMeta.addressConfig), + role: flagsToRole(extraMeta.isSigner, extraMeta.isWritable), + }; + } else if (extraMeta.discriminator === 2) { + const pubkey = await unpackPubkeyData(extraMeta.addressConfig, previousMetas, instructionData, accountRetriever); + return { + address: pubkey, + role: flagsToRole(extraMeta.isSigner, extraMeta.isWritable), + }; + } + + let seedProgramId: Address = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + + if (extraMeta.discriminator === 1) { + seedProgramId = programId; + } else { + const accountIndex = extraMeta.discriminator - (1 << 7); + if (previousMetas.length <= accountIndex) { + throw new TokenTransferHookAccountNotFound(); + } + seedProgramId = previousMetas[accountIndex].address; + } + + const seeds = await unpackSeeds(extraMeta.addressConfig, previousMetas, instructionData, accountRetriever); + //console.log("seeds", seeds); + console.log("seedProgramId", seedProgramId); + for (const seed of seeds) { + console.log("seed", seed); + console.log("address: ",getAddressDecoder().decode(seed)); + } + const address = await getProgramDerivedAddress({ + programAddress: seedProgramId, + seeds, + }); + + return { address: address[0], role: flagsToRole(extraMeta.isSigner, extraMeta.isWritable) }; +} + + +function flagsToRole(isSigner: boolean, isWritable: boolean): AccountRole { + const signerRole = isSigner ? AccountRole.READONLY_SIGNER : AccountRole.READONLY; + const writableRole = isWritable ? AccountRole.WRITABLE : AccountRole.READONLY; + return mergeRoles(signerRole, writableRole); +} \ No newline at end of file diff --git a/packages/tlv-account-resolution/tsconfig.json b/packages/tlv-account-resolution/tsconfig.json new file mode 100644 index 0000000..01db065 --- /dev/null +++ b/packages/tlv-account-resolution/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"], + "types": ["jest", "node"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 77dfc78..8b7f45d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,11 +27,54 @@ importers: specifier: ^5.0.0 version: 5.8.3 + packages/abl: + dependencies: + '@solana/kit': + specifier: 2.3.0 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + gill: + specifier: ^0.10.2 + version: 0.10.2(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + typescript: + specifier: ^5.0.0 + version: 5.8.3 + devDependencies: + '@codama/cli': + specifier: 1.2.1 + version: 1.2.1(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@types/jest': + specifier: ^29.5.0 + version: 29.5.14 + '@typescript-eslint/eslint-plugin': + specifier: ^8.34.0 + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.34.0 + version: 8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.32.0 + version: 9.32.0(jiti@1.21.7) + jest: + specifier: ^29.5.0 + version: 29.7.0(@types/node@20.19.9) + ts-jest: + specifier: ^29.1.0 + version: 29.4.0(@babel/core@7.28.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.0))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.9))(typescript@5.8.3) + packages/cli: dependencies: + '@mosaic/abl': + specifier: workspace:* + version: link:../abl + '@mosaic/ebalts': + specifier: workspace:* + version: link:../ebalts '@mosaic/sdk': specifier: workspace:* version: link:../sdk + '@mosaic/tlv-account-resolution': + specifier: workspace:* + version: link:../tlv-account-resolution '@solana/accounts': specifier: ^2.3.0 version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -49,7 +92,7 @@ importers: version: 12.1.0 gill: specifier: ^0.10.2 - version: 0.10.2(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 0.10.2(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) ora: specifier: ^8.0.1 version: 8.2.0 @@ -73,11 +116,54 @@ importers: specifier: ^5.0.0 version: 5.8.3 - packages/sdk: + packages/ebalts: dependencies: + '@mosaic/tlv-account-resolution': + specifier: workspace:* + version: link:../tlv-account-resolution + '@solana/kit': + specifier: 2.3.0 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) gill: specifier: ^0.10.2 version: 0.10.2(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + typescript: + specifier: ^5.0.0 + version: 5.8.3 + devDependencies: + '@types/jest': + specifier: ^29.5.0 + version: 29.5.14 + '@typescript-eslint/eslint-plugin': + specifier: ^8.34.0 + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.34.0 + version: 8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.32.0 + version: 9.32.0(jiti@1.21.7) + jest: + specifier: ^29.5.0 + version: 29.7.0(@types/node@20.19.9) + ts-jest: + specifier: ^29.1.0 + version: 29.4.0(@babel/core@7.28.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.0))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.9))(typescript@5.8.3) + + packages/sdk: + dependencies: + '@mosaic/abl': + specifier: workspace:* + version: link:../abl + '@mosaic/ebalts': + specifier: workspace:* + version: link:../ebalts + '@mosaic/tlv-account-resolution': + specifier: workspace:* + version: link:../tlv-account-resolution + gill: + specifier: ^0.10.2 + version: 0.10.2(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) devDependencies: '@types/jest': specifier: ^29.5.0 @@ -101,6 +187,37 @@ importers: specifier: ^5.8.3 version: 5.8.3 + packages/tlv-account-resolution: + dependencies: + '@solana/kit': + specifier: 2.3.0 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + gill: + specifier: ^0.10.2 + version: 0.10.2(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + typescript: + specifier: ^5.0.0 + version: 5.8.3 + devDependencies: + '@types/jest': + specifier: ^29.5.0 + version: 29.5.14 + '@typescript-eslint/eslint-plugin': + specifier: ^8.34.0 + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.34.0 + version: 8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.32.0 + version: 9.32.0(jiti@1.21.7) + jest: + specifier: ^29.5.0 + version: 29.7.0(@types/node@20.19.9) + ts-jest: + specifier: ^29.1.0 + version: 29.4.0(@babel/core@7.28.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.0))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.9))(typescript@5.8.3) + packages/ui: dependencies: '@mosaic/sdk': @@ -208,7 +325,7 @@ importers: version: 15.4.5(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3) eslint-plugin-import: specifier: ^2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@1.21.7)) postcss: specifier: ^8.4.32 version: 8.5.6 @@ -401,6 +518,47 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@codama/cli@1.2.1': + resolution: {integrity: sha512-Ag/ull1/9pOOZIeWu6GEth6PKiF5XFQSePRYFU+FWNiqeQZkcN5NIiougjBur9ni70ypbtC42gDsVPVBi6bPlA==} + hasBin: true + + '@codama/errors@1.3.1': + resolution: {integrity: sha512-tsQ83+8RRV7lXcRuSqRZJCjEM0gsVGo4PXAKL9dokUJzSTMMPQU4y87ExUps5KjeXQf6MkfOzYnGKqGf4FtU4g==} + hasBin: true + + '@codama/node-types@1.3.1': + resolution: {integrity: sha512-tpZwqOnCNXs1aLj95+ZjQW3K96LkiekqsYFTmuJxgspWoR3Ro+NDQEoxD3j5364hIYt0VfjcZlAcFD6y95GaQA==} + + '@codama/nodes-from-anchor@1.2.3': + resolution: {integrity: sha512-0ALDfHPGqYZLk86LBZ3LVR3dHiJm0h1VsqLHlM7wF/Gikt4z4bKR/vld/3larAt80HFNxptLB0zDGy513jhY8Q==} + + '@codama/nodes@1.3.1': + resolution: {integrity: sha512-ipmZFoX8Q7+2tKLOrTwcZ4R9eurhDyPU/oZ8I+2jNAuFEEW5mUewdNdeCt8xcq+vduovAd2BuvC3eJp2WbohCQ==} + + '@codama/renderers-core@1.0.17': + resolution: {integrity: sha512-pH0tyCrkhmmc84V5kAfXAiaTn+FPPW8nM530cZWneWr2q12frgmCtmIwrGcRKyqDPnS/dJ05P+y/TOZMit+Ldg==} + + '@codama/renderers-js-umi@1.1.17': + resolution: {integrity: sha512-tVUfD4JB3RDT4qq9c7DA+3fLF1YlG2WKbQqh1TLJN2hXUOY/mrb+EjVnGuWw23GiPIsB26l4kmg1de9ZI5tdHg==} + + '@codama/renderers-js@1.3.2': + resolution: {integrity: sha512-LDYurCw+rWVMlRiZSClQFYdV52TmEMjMBsP3HBUID4I0WQcZhQYzlnQEQbasnlBSHuVOLvjGEMztC7g2yioZIg==} + + '@codama/renderers-rust@1.1.3': + resolution: {integrity: sha512-hUk9yFfyq376x41jU4sSUAx3CKemybGH6mjqmIvMmjPPcupPxdoRPkI+CpidbfNMlkSG6vlpJR5CHSR3j909eQ==} + + '@codama/renderers@1.0.28': + resolution: {integrity: sha512-3/GLY/V/Uuw/gEG8/OpSC+SgdcBX+2ksUXXbOuBn1dqf2s3QoGRDRsCfMy0Bu+CkrO+epDUQmV2+IbwXfkS/lg==} + + '@codama/validators@1.3.1': + resolution: {integrity: sha512-xgPz3dzUirrS+qkxQpFHm+g4WhUW8ff7wfgjzZEVnaMrc8qKhOPgFO8b0WwPVZSytUMTdhqIpa+zLNZg8vvzNw==} + + '@codama/visitors-core@1.3.1': + resolution: {integrity: sha512-dlwzywaJEKO22QC/E3LpfVqNbSkTBXzFVR6pSGhWan/MNn//UR5+jyp3bFIKr+KPFDq+czilgFvFvllq5XFAXw==} + + '@codama/visitors@1.3.1': + resolution: {integrity: sha512-C6JZB9HrsPw7ZFogU+b8S7yRqznHpDuskyCY3103ZLknNs0SadOrry22ITQrS3Q3TETGGu3LOk8nu86CuLYl/Q==} + '@emnapi/core@1.4.5': resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==} @@ -2684,6 +2842,9 @@ packages: '@xrplf/secret-numbers@1.0.0': resolution: {integrity: sha512-qsCLGyqe1zaq9j7PZJopK+iGTGRbk6akkg6iZXJJgxKwck0C5x5Gnwlb1HKYGOwPKyrXWpV6a2YmcpNpUFctGg==} + a-sync-waterfall@1.0.1: + resolution: {integrity: sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==} + abitype@1.0.8: resolution: {integrity: sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==} peerDependencies: @@ -3226,6 +3387,10 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} + commander@5.1.0: + resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} + engines: {node: '>= 6'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -4914,6 +5079,16 @@ packages: nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + nunjucks@3.2.4: + resolution: {integrity: sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==} + engines: {node: '>= 6.9.0'} + hasBin: true + peerDependencies: + chokidar: ^3.3.0 + peerDependenciesMeta: + chokidar: + optional: true + ob1@0.82.5: resolution: {integrity: sha512-QyQQ6e66f+Ut/qUVjEce0E/wux5nAGLXYZDn1jr15JWstHsCH3l6VVrg8NKDptW9NEiBXKOJeGF/ydxeSDF3IQ==} engines: {node: '>=18.18'} @@ -6578,6 +6753,124 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} + '@codama/cli@1.2.1(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@codama/nodes': 1.3.1 + '@codama/nodes-from-anchor': 1.2.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@codama/renderers': 1.0.28(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@codama/renderers-js': 1.3.2(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@codama/renderers-js-umi': 1.1.17(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@codama/renderers-rust': 1.1.3(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@codama/visitors': 1.3.1 + '@codama/visitors-core': 1.3.1 + commander: 14.0.0 + picocolors: 1.1.1 + prompts: 2.4.2 + transitivePeerDependencies: + - chokidar + - fastestsmallesttextencoderdecoder + - typescript + + '@codama/errors@1.3.1': + dependencies: + '@codama/node-types': 1.3.1 + chalk: 5.4.1 + commander: 14.0.0 + + '@codama/node-types@1.3.1': {} + + '@codama/nodes-from-anchor@1.2.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@codama/errors': 1.3.1 + '@codama/nodes': 1.3.1 + '@codama/visitors': 1.3.1 + '@noble/hashes': 1.8.0 + '@solana/codecs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - typescript + + '@codama/nodes@1.3.1': + dependencies: + '@codama/errors': 1.3.1 + '@codama/node-types': 1.3.1 + + '@codama/renderers-core@1.0.17': + dependencies: + '@codama/errors': 1.3.1 + '@codama/nodes': 1.3.1 + '@codama/visitors-core': 1.3.1 + + '@codama/renderers-js-umi@1.1.17(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@codama/errors': 1.3.1 + '@codama/nodes': 1.3.1 + '@codama/renderers-core': 1.0.17 + '@codama/validators': 1.3.1 + '@codama/visitors-core': 1.3.1 + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + nunjucks: 3.2.4(chokidar@3.6.0) + prettier: 3.6.2 + transitivePeerDependencies: + - chokidar + - fastestsmallesttextencoderdecoder + - typescript + + '@codama/renderers-js@1.3.2(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@codama/errors': 1.3.1 + '@codama/nodes': 1.3.1 + '@codama/renderers-core': 1.0.17 + '@codama/visitors-core': 1.3.1 + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + nunjucks: 3.2.4(chokidar@3.6.0) + prettier: 3.6.2 + transitivePeerDependencies: + - chokidar + - fastestsmallesttextencoderdecoder + - typescript + + '@codama/renderers-rust@1.1.3(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@codama/errors': 1.3.1 + '@codama/nodes': 1.3.1 + '@codama/renderers-core': 1.0.17 + '@codama/visitors-core': 1.3.1 + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + nunjucks: 3.2.4(chokidar@3.6.0) + transitivePeerDependencies: + - chokidar + - fastestsmallesttextencoderdecoder + - typescript + + '@codama/renderers@1.0.28(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@codama/renderers-js': 1.3.2(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@codama/renderers-js-umi': 1.1.17(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@codama/renderers-rust': 1.1.3(chokidar@3.6.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + transitivePeerDependencies: + - chokidar + - fastestsmallesttextencoderdecoder + - typescript + + '@codama/validators@1.3.1': + dependencies: + '@codama/errors': 1.3.1 + '@codama/nodes': 1.3.1 + '@codama/visitors-core': 1.3.1 + + '@codama/visitors-core@1.3.1': + dependencies: + '@codama/errors': 1.3.1 + '@codama/nodes': 1.3.1 + json-stable-stringify: 1.3.0 + + '@codama/visitors@1.3.1': + dependencies: + '@codama/errors': 1.3.1 + '@codama/nodes': 1.3.1 + '@codama/visitors-core': 1.3.1 + '@emnapi/core@1.4.5': dependencies: '@emnapi/wasi-threads': 1.0.4 @@ -7954,6 +8247,10 @@ snapshots: dependencies: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana-program/address-lookup-table@0.7.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': + dependencies: + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana-program/compute-budget@0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -7962,6 +8259,10 @@ snapshots: dependencies: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana-program/compute-budget@0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': + dependencies: + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana-program/stake@0.2.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -7974,6 +8275,10 @@ snapshots: dependencies: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana-program/system@0.7.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': + dependencies: + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': dependencies: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -7984,6 +8289,11 @@ snapshots: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/sysvars': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': + dependencies: + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/sysvars': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana-program/token@0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -8088,6 +8398,31 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/instructions': 2.3.0(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/programs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/signers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/sysvars': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -8364,6 +8699,23 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/promises': 2.3.0(typescript@5.8.3) + '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -10186,6 +10538,8 @@ snapshots: - bufferutil - utf-8-validate + a-sync-waterfall@1.0.1: {} + abitype@1.0.8(typescript@5.8.3)(zod@3.22.4): optionalDependencies: typescript: 5.8.3 @@ -10808,6 +11162,8 @@ snapshots: commander@4.1.1: {} + commander@5.1.0: {} + concat-map@0.0.1: {} connect@3.7.0: @@ -11269,8 +11625,8 @@ snapshots: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3) eslint: 9.32.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@1.21.7)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@1.21.7)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@1.21.7)) eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@1.21.7)) eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@1.21.7)) @@ -11289,7 +11645,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@1.21.7)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 @@ -11300,22 +11656,22 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@1.21.7)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3) eslint: 9.32.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@1.21.7)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@1.21.7)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -11326,7 +11682,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.32.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@1.21.7)))(eslint@9.32.0(jiti@1.21.7)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -11715,6 +12071,22 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + gill@0.10.2(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3): + dependencies: + '@solana-program/address-lookup-table': 0.7.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana-program/compute-budget': 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana-program/system': 0.7.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana-program/token-2022': 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana/assertions': 2.3.0(typescript@5.8.3) + '@solana/codecs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - '@solana/sysvars' + - fastestsmallesttextencoderdecoder + - ws + gill@0.10.2(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)): dependencies: '@solana-program/address-lookup-table': 0.7.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) @@ -12986,6 +13358,14 @@ snapshots: nullthrows@1.1.1: {} + nunjucks@3.2.4(chokidar@3.6.0): + dependencies: + a-sync-waterfall: 1.0.1 + asap: 2.0.6 + commander: 5.1.0 + optionalDependencies: + chokidar: 3.6.0 + ob1@0.82.5: dependencies: flow-enums-runtime: 0.0.6 diff --git a/tsconfig.json b/tsconfig.json index c91253c..7a0679b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,8 +24,11 @@ "paths": { "@mosaic/core": ["./packages/core/src"], "@mosaic/sdk": ["./packages/sdk/src"], + "@mosaic/tlv-account-resolution": ["./packages/tlv-account-resolution/src"], + "@mosaic/ebalts": ["./packages/ebalts/src"], "@mosaic/cli": ["./packages/cli/src"], - "@mosaic/ui": ["./packages/ui/src"] + "@mosaic/ui": ["./packages/ui/src"], + "@mosaic/abl": ["./packages/abl/src"] } }, "include": ["packages/*/src/**/*", "*.ts", "*.tsx"], From f2b5f55ce570d0925b5e2406fdcbd932ab39cb6b Mon Sep 17 00:00:00 2001 From: tiago Date: Thu, 31 Jul 2025 12:39:42 +0100 Subject: [PATCH 2/9] Added docs. --- packages/sdk/src/abl/createList.ts | 24 ++++++++++++++ packages/sdk/src/abl/setExtraMetas.ts | 28 ++++++++++++++++ packages/sdk/src/abl/utils.ts | 7 +++- packages/sdk/src/ebalts/createConfig.ts | 28 ++++++++++++++++ .../src/ebalts/enablePermissionlessThaw.ts | 27 +++++++++++++++ packages/sdk/src/ebalts/setGatingProgram.ts | 28 ++++++++++++++++ packages/sdk/src/ebalts/thawPermissionless.ts | 33 +++++++++++++++++++ packages/sdk/src/ebalts/utils.ts | 6 +++- 8 files changed, 179 insertions(+), 2 deletions(-) diff --git a/packages/sdk/src/abl/createList.ts b/packages/sdk/src/abl/createList.ts index 25791a8..56820f7 100644 --- a/packages/sdk/src/abl/createList.ts +++ b/packages/sdk/src/abl/createList.ts @@ -3,6 +3,17 @@ import { ABL_PROGRAM_ID } from "./utils"; import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; +/** + * Generates instructions for creating a new allowlist/blocklist configuration. + * + * This function creates the necessary instructions to initialize a list configuration + * that can be used for gating token operations. The list can be configured as either + * an allowlist or blocklist depending on the mode. + * + * @param input - Configuration parameters for list creation + * @param input.authority - The authority signer who will control the list configuration + * @returns Promise containing the instructions and the list configuration address + */ export const getCreateListInstructions = async (input: { authority: TransactionSigner; }): Promise<{instructions: Instruction[], listConfig: Address}> => { @@ -25,6 +36,19 @@ export const getCreateListInstructions = async (input: { }; } +/** + * Creates a complete transaction for initializing a new allowlist/blocklist configuration. + * + * This function builds a full transaction that can be signed and sent to create + * a list configuration. The transaction includes the necessary instructions and + * uses the latest blockhash for proper transaction construction. + * + * @param input - Configuration parameters for the transaction + * @param input.rpc - The Solana RPC client instance + * @param input.payer - The transaction fee payer signer + * @param input.authority - The authority signer who will control the list configuration + * @returns Promise containing the full transaction and the list configuration address + */ export const getCreateListTransaction = async (input: { rpc: Rpc; payer: TransactionSigner; diff --git a/packages/sdk/src/abl/setExtraMetas.ts b/packages/sdk/src/abl/setExtraMetas.ts index 7ccf1c2..ca8d99b 100644 --- a/packages/sdk/src/abl/setExtraMetas.ts +++ b/packages/sdk/src/abl/setExtraMetas.ts @@ -5,6 +5,19 @@ import { findMintConfigPda, findThawExtraMetasAccountPda } from '@mosaic/ebalts' import { EBALTS_PROGRAM_ID } from "../ebalts"; +/** + * Generates instructions for setting extra metadata thaw configuration for a token. + * + * This function creates instructions to configure the extra accounts metadata + * on a specific mint, effectively assigning a specific allow / block list to a token account. + * This is used in conjunction with the EBALTS program to permissionlessly thaw token accounts. + * + * @param input - Configuration parameters for setting extra metadata thaw + * @param input.authority - The authority signer who can modify the thaw configuration + * @param input.mint - The mint address for which to configure extra metadata thaw + * @param input.list - The list configuration address that controls the thaw permissions + * @returns Promise containing the instructions for setting extra metadata thaw + */ export const getSetExtraMetasInstructions = async (input: { authority: TransactionSigner; mint: Address; @@ -27,6 +40,21 @@ export const getSetExtraMetasInstructions = async (input: { return [createListInstruction]; } +/** + * Creates a complete transaction for setting extra metadata thaw configuration for a token. + * + * This function builds a full transaction that can be signed and sent to configure + * the thaw settings for extra metadata on a specific mint. The transaction includes + * the necessary instructions and uses the latest blockhash for proper construction. + * + * @param input - Configuration parameters for the transaction + * @param input.rpc - The Solana RPC client instance + * @param input.payer - The transaction fee payer signer + * @param input.authority - The authority signer who can modify the thaw configuration + * @param input.mint - The mint address for which to configure extra metadata thaw + * @param input.list - The list configuration address that controls the thaw permissions + * @returns Promise containing the full transaction for setting extra metadata thaw + */ export const getSetExtraMetasTransaction = async (input: { rpc: Rpc; payer: TransactionSigner; diff --git a/packages/sdk/src/abl/utils.ts b/packages/sdk/src/abl/utils.ts index be68de0..2978b4a 100644 --- a/packages/sdk/src/abl/utils.ts +++ b/packages/sdk/src/abl/utils.ts @@ -1,4 +1,9 @@ import type { Address } from "gill"; - +/** + * The program ID for the ABL (Allowlist/Blocklist) program. + * + * This is the address of the ABL program that handles allowlist and blocklist + * functionality for token gating and access control. + */ export const ABL_PROGRAM_ID = '8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N' as Address; \ No newline at end of file diff --git a/packages/sdk/src/ebalts/createConfig.ts b/packages/sdk/src/ebalts/createConfig.ts index 8affa72..7fc2320 100644 --- a/packages/sdk/src/ebalts/createConfig.ts +++ b/packages/sdk/src/ebalts/createConfig.ts @@ -5,6 +5,19 @@ import { findMintConfigPda, getCreateConfigInstruction } from "@mosaic/ebalts"; import { EBALTS_PROGRAM_ID } from "./utils"; +/** + * Generates instructions for creating a new EBALTS mint configuration. + * + * This function creates the necessary instructions to initialize a mint configuration + * for the EBALTS program. This configuration enables enhanced balance features like + * gating programs and permissionless thaw operations for a specific mint. + * + * @param input - Configuration parameters for EBALTS mint config creation + * @param input.authority - The authority signer who will control the mint configuration + * @param input.mint - The mint address for which to create the configuration + * @param input.gatingProgram - The program address that will gate operations on this mint + * @returns Promise containing the instructions and the mint configuration address + */ export const getCreateConfigInstructions = async (input: { authority: TransactionSigner; mint: Address; @@ -28,6 +41,21 @@ export const getCreateConfigInstructions = async (input: { }; } +/** + * Creates a complete transaction for initializing a new EBALTS mint configuration. + * + * This function builds a full transaction that can be signed and sent to create + * an EBALTS mint configuration. The transaction includes the necessary instructions + * and uses the latest blockhash for proper transaction construction. + * + * @param input - Configuration parameters for the transaction + * @param input.rpc - The Solana RPC client instance + * @param input.payer - The transaction fee payer signer + * @param input.authority - The authority signer who will control the mint configuration + * @param input.mint - The mint address for which to create the configuration + * @param input.gatingProgram - The program address that will gate operations on this mint + * @returns Promise containing the full transaction and the mint configuration address + */ export const getCreateConfigTransaction = async (input: { rpc: Rpc; payer: TransactionSigner; diff --git a/packages/sdk/src/ebalts/enablePermissionlessThaw.ts b/packages/sdk/src/ebalts/enablePermissionlessThaw.ts index 1f4f138..63e186d 100644 --- a/packages/sdk/src/ebalts/enablePermissionlessThaw.ts +++ b/packages/sdk/src/ebalts/enablePermissionlessThaw.ts @@ -5,6 +5,19 @@ import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstr import { EBALTS_PROGRAM_ID } from "./utils"; +/** + * Generates instructions for enabling permissionless thaw operations on a mint. + * + * This function creates instructions to enable permissionless thaw functionality + * for a specific mint. When enabled, any user can thaw frozen token accounts + * without requiring the freeze authority's signature, while freeze operations + * remain restricted to the authority. + * + * @param input - Configuration parameters for enabling permissionless thaw + * @param input.authority - The authority signer who can modify the thaw configuration + * @param input.mint - The mint address for which to enable permissionless thaw + * @returns Promise containing the instructions for enabling permissionless thaw + */ export const getEnablePermissionlessThawInstructions = async (input: { authority: TransactionSigner; mint: Address; @@ -23,6 +36,20 @@ export const getEnablePermissionlessThawInstructions = async (input: { return [enablePermissionlessThawInstruction]; } +/** + * Creates a complete transaction for enabling permissionless thaw operations. + * + * This function builds a full transaction that can be signed and sent to enable + * permissionless thaw functionality for a specific mint. The transaction includes + * the necessary instructions and uses the latest blockhash for proper construction. + * + * @param input - Configuration parameters for the transaction + * @param input.rpc - The Solana RPC client instance + * @param input.payer - The transaction fee payer signer + * @param input.authority - The authority signer who can modify the thaw configuration + * @param input.mint - The mint address for which to enable permissionless thaw + * @returns Promise containing the full transaction for enabling permissionless thaw + */ export const getEnablePermissionlessThawTransaction = async (input: { rpc: Rpc; payer: TransactionSigner; diff --git a/packages/sdk/src/ebalts/setGatingProgram.ts b/packages/sdk/src/ebalts/setGatingProgram.ts index a44d337..13ceab6 100644 --- a/packages/sdk/src/ebalts/setGatingProgram.ts +++ b/packages/sdk/src/ebalts/setGatingProgram.ts @@ -5,6 +5,19 @@ import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstr import { EBALTS_PROGRAM_ID } from "./utils"; +/** + * Generates instructions for setting or updating the gating program for a mint. + * + * This function creates instructions to configure which program will gate operations + * on a specific mint. The gating program controls access to the permissionless thaw functionality. + * If no gating program is provided, it defaults to the System Program (11111111111111111111111111111111). + * + * @param input - Configuration parameters for setting the gating program + * @param input.authority - The authority signer who can modify the gating configuration + * @param input.mint - The mint address for which to set the gating program + * @param input.gatingProgram - The program address that will gate operations on this mint + * @returns Promise containing the instructions for setting the gating program + */ export const getSetGatingProgramInstructions = async (input: { authority: TransactionSigner; mint: Address; @@ -24,6 +37,21 @@ export const getSetGatingProgramInstructions = async (input: { return [setGatingProgramInstruction]; } +/** + * Creates a complete transaction for setting or updating the gating program. + * + * This function builds a full transaction that can be signed and sent to configure + * the gating program for a specific mint. The transaction includes the necessary + * instructions and uses the latest blockhash for proper construction. + * + * @param input - Configuration parameters for the transaction + * @param input.rpc - The Solana RPC client instance + * @param input.payer - The transaction fee payer signer + * @param input.authority - The authority signer who can modify the gating configuration + * @param input.mint - The mint address for which to set the gating program + * @param input.gatingProgram - The program address that will gate operations on this mint + * @returns Promise containing the full transaction for setting the gating program + */ export const getSetGatingProgramTransaction = async (input: { rpc: Rpc; payer: TransactionSigner; diff --git a/packages/sdk/src/ebalts/thawPermissionless.ts b/packages/sdk/src/ebalts/thawPermissionless.ts index a2c74ff..24cd93d 100644 --- a/packages/sdk/src/ebalts/thawPermissionless.ts +++ b/packages/sdk/src/ebalts/thawPermissionless.ts @@ -6,6 +6,22 @@ import { EBALTS_PROGRAM_ID } from "./utils"; import { getTokenEncoder, AccountState, TOKEN_2022_PROGRAM_ADDRESS, AuthorityType } from "gill/programs"; +/** + * Generates instructions for performing a permissionless thaw operation on a token account. + * + * This function creates instructions to thaw a frozen token account without requiring + * the freeze authority's signature. This is only possible if permissionless thaw has + * been enabled for the mint. The function includes logic to handle extra accounts resolution + * that may be required to perform the thaw. + * + * @param input - Configuration parameters for the permissionless thaw operation + * @param input.rpc - The Solana RPC client instance for fetching account data + * @param input.authority - The authority signer performing the thaw operation + * @param input.mint - The mint address of the token being thawed + * @param input.tokenAccount - The token account address to thaw + * @param input.tokenAccountOwner - The owner of the token account + * @returns Promise containing the instructions for the permissionless thaw operation + */ export const getThawPermissionlessInstructions = async (input: { rpc: Rpc; authority: TransactionSigner; @@ -48,6 +64,23 @@ export const getThawPermissionlessInstructions = async (input: { return [thawPermissionlessInstruction]; } +/** + * Creates a complete transaction for performing a permissionless thaw operation. + * + * This function builds a full transaction that can be signed and sent to thaw + * a frozen token account without requiring the freeze authority's signature. + * The transaction includes the necessary instructions and uses the latest + * blockhash for proper construction. + * + * @param input - Configuration parameters for the transaction + * @param input.rpc - The Solana RPC client instance + * @param input.payer - The transaction fee payer signer + * @param input.authority - The authority signer performing the thaw operation + * @param input.mint - The mint address of the token being thawed + * @param input.tokenAccount - The token account address to thaw + * @param input.tokenAccountOwner - The owner of the token account + * @returns Promise containing the full transaction for the permissionless thaw operation + */ export const getThawPermissionlessTransaction = async (input: { rpc: Rpc; payer: TransactionSigner; diff --git a/packages/sdk/src/ebalts/utils.ts b/packages/sdk/src/ebalts/utils.ts index 9cdcc46..8570917 100644 --- a/packages/sdk/src/ebalts/utils.ts +++ b/packages/sdk/src/ebalts/utils.ts @@ -1,4 +1,8 @@ import type { Address } from "gill"; - +/** + * The program ID for the EBALTS program. + * + * This is the address of the EBALTS program that provides the ability to permissionlessly thaw token accounts. + */ export const EBALTS_PROGRAM_ID = '81H44JYqk1p8RUks7pNJjhQG4Pj8FcaJeTUxZKN3JfLc' as Address; \ No newline at end of file From 610e9d8eef641ca308f5f252e5a06d23ad5d26dc Mon Sep 17 00:00:00 2001 From: tiago Date: Thu, 31 Jul 2025 12:46:43 +0100 Subject: [PATCH 3/9] cleanup --- packages/cli/src/commands/abl/createList.ts | 28 ++++----------- .../cli/src/commands/abl/setExtraMetas.ts | 28 ++++----------- .../cli/src/commands/ebalts/createConfig.ts | 21 +---------- .../ebalts/enablePermissionlessThaw.ts | 28 +++------------ .../src/commands/ebalts/setGatingProgram.ts | 35 +++++-------------- .../src/commands/ebalts/thawPermissionless.ts | 31 ++++------------ packages/tlv-account-resolution/src/state.ts | 10 +----- 7 files changed, 34 insertions(+), 147 deletions(-) diff --git a/packages/cli/src/commands/abl/createList.ts b/packages/cli/src/commands/abl/createList.ts index 60febbd..621f14d 100644 --- a/packages/cli/src/commands/abl/createList.ts +++ b/packages/cli/src/commands/abl/createList.ts @@ -1,16 +1,11 @@ import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; -import { createArcadeTokenInitTransaction, getCreateListTransaction } from '@mosaic/sdk'; +import { getCreateListTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { - compressTransactionMessageUsingAddressLookupTables, - createTransaction, - generateKeyPairSigner, signTransactionMessageWithSigners, - SolanaError, - type Address, } from 'gill'; interface CreateConfigOptions { @@ -26,14 +21,12 @@ export const createList = new Command('create-list') const spinner = ora('Creating ebalts config...').start(); try { - const parentOpts = command.parent?.parent?.opts() || {}; - const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); - console.log(options); - console.log(parentOpts); const {transaction, listConfig} = await getCreateListTransaction({ rpc, @@ -53,7 +46,7 @@ export const createList = new Command('create-list') // Send and confirm transaction const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); - spinner.succeed('Ebalts config created successfully!'); + spinner.succeed('ABL list created successfully!'); // Display results console.log(chalk.green('✅ ABL list created successfully!')); @@ -62,21 +55,12 @@ export const createList = new Command('create-list') console.log(` ${chalk.bold('Transaction:')} ${signature}`); } catch (error) { - spinner.fail('Failed to create ebalts config'); + spinner.fail('Failed to create ABL list'); console.error( chalk.red('❌ Error:'), error instanceof Error ? error.message : 'Unknown error' ); - console.error( - chalk.red('❌ Error:'), - error - ); - console.error( - chalk.red('❌ Error:'), - error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' - ); - process.exit(1); } }); \ No newline at end of file diff --git a/packages/cli/src/commands/abl/setExtraMetas.ts b/packages/cli/src/commands/abl/setExtraMetas.ts index 80bb2a0..a2c50ce 100644 --- a/packages/cli/src/commands/abl/setExtraMetas.ts +++ b/packages/cli/src/commands/abl/setExtraMetas.ts @@ -1,15 +1,11 @@ import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; -import { createArcadeTokenInitTransaction, getSetExtraMetasTransaction } from '@mosaic/sdk'; +import { getSetExtraMetasTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { - compressTransactionMessageUsingAddressLookupTables, - createTransaction, - generateKeyPairSigner, signTransactionMessageWithSigners, - SolanaError, type Address, } from 'gill'; @@ -28,14 +24,11 @@ export const setExtraMetas = new Command('set-extra-metas') const spinner = ora('Setting extra metas...').start(); try { - const parentOpts = command.parent?.parent?.opts() || {}; - const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(keypairPath); - - console.log(options); - console.log(parentOpts); const transaction = await getSetExtraMetasTransaction({ rpc, @@ -61,23 +54,16 @@ export const setExtraMetas = new Command('set-extra-metas') // Display results console.log(chalk.green('✅ Extra metas set successfully!')); + console.log(chalk.cyan('📋 Details:')); + console.log(` ${chalk.bold('Transaction:')} ${signature}`); } catch (error) { - spinner.fail('Failed to create ebalts config'); + spinner.fail('Failed to set extra metas'); console.error( chalk.red('❌ Error:'), error instanceof Error ? error.message : 'Unknown error' ); - console.error( - chalk.red('❌ Error:'), - error - ); - console.error( - chalk.red('❌ Error:'), - error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' - ); - process.exit(1); } }); \ No newline at end of file diff --git a/packages/cli/src/commands/ebalts/createConfig.ts b/packages/cli/src/commands/ebalts/createConfig.ts index 86d17c9..7405609 100644 --- a/packages/cli/src/commands/ebalts/createConfig.ts +++ b/packages/cli/src/commands/ebalts/createConfig.ts @@ -1,19 +1,14 @@ import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; -import { createArcadeTokenInitTransaction, getCreateConfigTransaction } from '@mosaic/sdk'; +import { getCreateConfigTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { - compressTransactionMessageUsingAddressLookupTables, - createTransaction, - generateKeyPairSigner, signTransactionMessageWithSigners, SolanaError, type Address, } from 'gill'; -import { findMintConfigPda, getCreateConfigInstruction } from '@mosaic/ebalts'; -import { EBALTS_PROGRAM_ID } from './util.js'; interface CreateConfigOptions { mint: string; @@ -26,8 +21,6 @@ export const createConfig = new Command('create') .description('Create a new ebalts config for an existing mint') .requiredOption('-m, --mint ', 'Mint address') .option('-g, --gating-program ', 'Gating program address') - //.option('-p, --payer ', 'Payer address') - //.option('-a, --authority ', 'Authority address') .action(async (options: CreateConfigOptions, command) => { const spinner = ora('Creating ebalts config...').start(); @@ -38,9 +31,6 @@ export const createConfig = new Command('create') const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); - console.log(options); - console.log(parentOpts); - const gatingProgram = (options.gatingProgram || '11111111111111111111111111111111') as Address; const {transaction, mintConfig} = await getCreateConfigTransaction({ @@ -80,15 +70,6 @@ export const createConfig = new Command('create') error instanceof Error ? error.message : 'Unknown error' ); - console.error( - chalk.red('❌ Error:'), - error - ); - console.error( - chalk.red('❌ Error:'), - error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' - ); - process.exit(1); } }); \ No newline at end of file diff --git a/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts index b446f2f..1c381dd 100644 --- a/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts +++ b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts @@ -1,19 +1,14 @@ import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; -import { createArcadeTokenInitTransaction, getEnablePermissionlessThawTransaction } from '@mosaic/sdk'; +import { getEnablePermissionlessThawTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { - compressTransactionMessageUsingAddressLookupTables, - createTransaction, - generateKeyPairSigner, signTransactionMessageWithSigners, SolanaError, type Address, } from 'gill'; -import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction, getTogglePermissionlessInstructionsInstruction } from '@mosaic/ebalts'; -import { EBALTS_PROGRAM_ID } from './util.js'; interface CreateConfigOptions { mint: string; @@ -29,15 +24,12 @@ export const enablePermissionlessThaw = new Command('enable-permissionless-thaw' const spinner = ora('Enabling permissionless thaw...').start(); try { - const parentOpts = command.parent?.parent?.opts() || {}; - const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); - console.log(options); - console.log(parentOpts); - spinner.text = 'Building transaction...'; const transaction = await getEnablePermissionlessThawTransaction({ @@ -68,21 +60,11 @@ export const enablePermissionlessThaw = new Command('enable-permissionless-thaw' console.log(` ${chalk.bold('Transaction:')} ${signature}`); } catch (error) { - spinner.fail('Failed to create ebalts config'); + spinner.fail('Failed to enable permissionless thaw'); console.error( chalk.red('❌ Error:'), error instanceof Error ? error.message : 'Unknown error' ); - - console.error( - chalk.red('❌ Error:'), - error - ); - console.error( - chalk.red('❌ Error:'), - error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' - ); - process.exit(1); } }); \ No newline at end of file diff --git a/packages/cli/src/commands/ebalts/setGatingProgram.ts b/packages/cli/src/commands/ebalts/setGatingProgram.ts index 1dc8bb5..235a078 100644 --- a/packages/cli/src/commands/ebalts/setGatingProgram.ts +++ b/packages/cli/src/commands/ebalts/setGatingProgram.ts @@ -1,18 +1,15 @@ import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; -import { createArcadeTokenInitTransaction, getSetGatingProgramTransaction } from '@mosaic/sdk'; +import { getSetGatingProgramTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { - compressTransactionMessageUsingAddressLookupTables, - createTransaction, - generateKeyPairSigner, signTransactionMessageWithSigners, SolanaError, type Address, } from 'gill'; -import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction } from '@mosaic/ebalts'; +import { findMintConfigPda } from '@mosaic/ebalts'; import { EBALTS_PROGRAM_ID } from './util.js'; interface CreateConfigOptions { @@ -30,20 +27,14 @@ export const setGatingProgram = new Command('set-gating-program') const spinner = ora('Setting gating program...').start(); try { - const parentOpts = command.parent?.parent?.opts() || {}; - const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); - console.log(options); - console.log(parentOpts); - - const signerAddress = kp.address; - const mintConfigPda = await findMintConfigPda({ mint: options.mint as Address }, { programAddress: EBALTS_PROGRAM_ID }); const gatingProgram = (options.gatingProgram || '11111111111111111111111111111111') as Address; - const transaction = await getSetGatingProgramTransaction({ rpc, @@ -53,7 +44,6 @@ export const setGatingProgram = new Command('set-gating-program') gatingProgram: gatingProgram, }); - spinner.text = 'Signing transaction...'; // Sign the transaction @@ -65,10 +55,10 @@ export const setGatingProgram = new Command('set-gating-program') // Send and confirm transaction const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); - spinner.succeed('Ebalts config created successfully!'); + spinner.succeed('Gating program set successfully!'); // Display results - console.log(chalk.green('✅ Ebalts config created successfully!')); + console.log(chalk.green('✅ Gating program set successfully!')); console.log(chalk.cyan('📋 Details:')); console.log(` ${chalk.bold('Mint:')} ${options.mint}`); console.log(` ${chalk.bold('Gating Program:')} ${options.gatingProgram}`); @@ -76,21 +66,12 @@ export const setGatingProgram = new Command('set-gating-program') console.log(` ${chalk.bold('Transaction:')} ${signature}`); } catch (error) { - spinner.fail('Failed to create ebalts config'); + spinner.fail('Failed to set gating program'); console.error( chalk.red('❌ Error:'), error instanceof Error ? error.message : 'Unknown error' ); - console.error( - chalk.red('❌ Error:'), - error - ); - console.error( - chalk.red('❌ Error:'), - error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' - ); - process.exit(1); } }); \ No newline at end of file diff --git a/packages/cli/src/commands/ebalts/thawPermissionless.ts b/packages/cli/src/commands/ebalts/thawPermissionless.ts index 4bafacc..526601e 100644 --- a/packages/cli/src/commands/ebalts/thawPermissionless.ts +++ b/packages/cli/src/commands/ebalts/thawPermissionless.ts @@ -1,25 +1,15 @@ import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; -import { createArcadeTokenInitTransaction, getThawPermissionlessTransaction } from '@mosaic/sdk'; +import { getThawPermissionlessTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { - compressTransactionMessageUsingAddressLookupTables, - createTransaction, - generateKeyPairSigner, signTransactionMessageWithSigners, SolanaError, type Address, - AccountRole, - fetchEncodedAccount, - lamports, } from 'gill'; -import { createThawPermissionlessInstructionWithExtraMetas, findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction } from '@mosaic/ebalts'; -import { EBALTS_PROGRAM_ID } from './util.js'; -import { AccountState, getAssociatedTokenAccountAddress, getTokenEncoder, TOKEN_2022_PROGRAM_ADDRESS } from 'gill/programs/token'; -import { ABL_PROGRAM_ID } from '../abl/utils.js'; -import { findABWalletPda } from '@mosaic/abl'; +import { getAssociatedTokenAccountAddress, TOKEN_2022_PROGRAM_ADDRESS } from 'gill/programs/token'; interface CreateConfigOptions { mint: string; @@ -34,9 +24,9 @@ export const thawPermissionless = new Command('thaw-permissionless') const spinner = ora('Thawing permissionless...').start(); try { - const parentOpts = command.parent?.parent?.opts() || {}; - const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; + const parentOpts = command.parent?.parent?.opts() || {}; + const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; + const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); @@ -84,20 +74,11 @@ export const thawPermissionless = new Command('thaw-permissionless') console.log(` ${chalk.bold('Transaction:')} ${signature}`); } catch (error) { - spinner.fail('Failed to create ebalts config'); + spinner.fail('Failed to thaw permissionless'); console.error( chalk.red('❌ Error:'), error instanceof Error ? error.message : 'Unknown error' ); - - console.error( - chalk.red('❌ Error:'), - error - ); - console.error( - chalk.red('❌ Error:'), - error instanceof SolanaError ? error : error instanceof Error ? error.message : 'Unknown error' - ); process.exit(1); } diff --git a/packages/tlv-account-resolution/src/state.ts b/packages/tlv-account-resolution/src/state.ts index 2454143..b1cf6d7 100644 --- a/packages/tlv-account-resolution/src/state.ts +++ b/packages/tlv-account-resolution/src/state.ts @@ -17,7 +17,6 @@ export async function resolveExtraMetas( const resolvedMetas = [...previousMetas]; for (const extraAccountMeta of extraAccountMetas) { const resolvedMeta = await resolveExtraAccountMeta(accountRetriever, extraAccountMeta, resolvedMetas, instructionData, programId); - console.log("resolvedMeta", resolvedMeta); resolvedMetas.push(resolvedMeta); } return resolvedMetas; @@ -64,8 +63,6 @@ export function unpackExtraAccountMetas( const count = new DataView(data.buffer, 12, 4).getUint32(0, true); const offset = 16; - console.log(length, count); - if (length !== count * 35 + 4) { throw new TokenTransferHookInvalidPubkeyData(); } @@ -125,12 +122,7 @@ export async function resolveExtraAccountMeta( } const seeds = await unpackSeeds(extraMeta.addressConfig, previousMetas, instructionData, accountRetriever); - //console.log("seeds", seeds); - console.log("seedProgramId", seedProgramId); - for (const seed of seeds) { - console.log("seed", seed); - console.log("address: ",getAddressDecoder().decode(seed)); - } + const address = await getProgramDerivedAddress({ programAddress: seedProgramId, seeds, From e222a9ec733f8d0797fa1162727ef6bc88d94933 Mon Sep 17 00:00:00 2001 From: tiago Date: Thu, 31 Jul 2025 17:05:23 +0100 Subject: [PATCH 4/9] lint and package linking fixes --- eslint.config.js | 2 +- packages/abl/tsconfig.json | 2 +- packages/cli/src/commands/abl/createList.ts | 1 - packages/cli/src/commands/ebalts/createConfig.ts | 2 -- .../src/commands/ebalts/enablePermissionlessThaw.ts | 2 -- packages/cli/src/commands/ebalts/setGatingProgram.ts | 2 -- packages/cli/src/commands/ebalts/thawPermissionless.ts | 2 -- packages/ebalts/src/index.ts | 2 +- packages/ebalts/tsconfig.json | 2 +- packages/sdk/src/abl/setExtraMetas.ts | 2 +- packages/sdk/src/ebalts/createConfig.ts | 4 +--- packages/sdk/src/ebalts/enablePermissionlessThaw.ts | 6 ++---- packages/sdk/src/ebalts/setGatingProgram.ts | 6 ++---- packages/sdk/src/ebalts/thawPermissionless.ts | 10 ++++------ packages/sdk/tsconfig.json | 1 - packages/tlv-account-resolution/src/pubkeyData.ts | 2 +- packages/tlv-account-resolution/src/seeds.ts | 5 +---- packages/tlv-account-resolution/src/state.ts | 4 ++-- 18 files changed, 18 insertions(+), 39 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index d45abdf..f18403d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -31,6 +31,6 @@ export default [ }, }, { - ignores: ['dist/', 'build/', 'node_modules/', '*.js'], + ignores: ['dist/', 'build/', 'node_modules/', '*.js', '**/generated/'], }, ]; diff --git a/packages/abl/tsconfig.json b/packages/abl/tsconfig.json index 01db065..f7d4c81 100644 --- a/packages/abl/tsconfig.json +++ b/packages/abl/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./dist", - "rootDir": "./src" + "verbatimModuleSyntax": false }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"], diff --git a/packages/cli/src/commands/abl/createList.ts b/packages/cli/src/commands/abl/createList.ts index 621f14d..280ec36 100644 --- a/packages/cli/src/commands/abl/createList.ts +++ b/packages/cli/src/commands/abl/createList.ts @@ -23,7 +23,6 @@ export const createList = new Command('create-list') try { const parentOpts = command.parent?.parent?.opts() || {}; const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); diff --git a/packages/cli/src/commands/ebalts/createConfig.ts b/packages/cli/src/commands/ebalts/createConfig.ts index 7405609..c0934ec 100644 --- a/packages/cli/src/commands/ebalts/createConfig.ts +++ b/packages/cli/src/commands/ebalts/createConfig.ts @@ -6,7 +6,6 @@ import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { signTransactionMessageWithSigners, - SolanaError, type Address, } from 'gill'; @@ -27,7 +26,6 @@ export const createConfig = new Command('create') try { const parentOpts = command.parent?.parent?.opts() || {}; const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); diff --git a/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts index 1c381dd..86c11b6 100644 --- a/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts +++ b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts @@ -6,7 +6,6 @@ import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { signTransactionMessageWithSigners, - SolanaError, type Address, } from 'gill'; @@ -26,7 +25,6 @@ export const enablePermissionlessThaw = new Command('enable-permissionless-thaw' try { const parentOpts = command.parent?.parent?.opts() || {}; const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); diff --git a/packages/cli/src/commands/ebalts/setGatingProgram.ts b/packages/cli/src/commands/ebalts/setGatingProgram.ts index 235a078..7b09883 100644 --- a/packages/cli/src/commands/ebalts/setGatingProgram.ts +++ b/packages/cli/src/commands/ebalts/setGatingProgram.ts @@ -6,7 +6,6 @@ import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { signTransactionMessageWithSigners, - SolanaError, type Address, } from 'gill'; import { findMintConfigPda } from '@mosaic/ebalts'; @@ -29,7 +28,6 @@ export const setGatingProgram = new Command('set-gating-program') try { const parentOpts = command.parent?.parent?.opts() || {}; const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); diff --git a/packages/cli/src/commands/ebalts/thawPermissionless.ts b/packages/cli/src/commands/ebalts/thawPermissionless.ts index 526601e..66c7c11 100644 --- a/packages/cli/src/commands/ebalts/thawPermissionless.ts +++ b/packages/cli/src/commands/ebalts/thawPermissionless.ts @@ -6,7 +6,6 @@ import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; import { signTransactionMessageWithSigners, - SolanaError, type Address, } from 'gill'; import { getAssociatedTokenAccountAddress, TOKEN_2022_PROGRAM_ADDRESS } from 'gill/programs/token'; @@ -26,7 +25,6 @@ export const thawPermissionless = new Command('thaw-permissionless') try { const parentOpts = command.parent?.parent?.opts() || {}; const rpcUrl = options.rpcUrl || parentOpts.rpcUrl; - const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); diff --git a/packages/ebalts/src/index.ts b/packages/ebalts/src/index.ts index f883596..849de23 100644 --- a/packages/ebalts/src/index.ts +++ b/packages/ebalts/src/index.ts @@ -1,4 +1,4 @@ -import { type Address, type Rpc, type GetAccountInfoApi, type Instruction, fetchEncodedAccount, type TransactionSigner, AccountRole, type AccountMeta, type MaybeEncodedAccount } from '@solana/kit'; +import { type Address, type Instruction, type TransactionSigner, AccountRole, type AccountMeta, type MaybeEncodedAccount } from '@solana/kit'; import { findMintConfigPda } from './generated/pdas/mintConfig'; import { findFreezeExtraMetasAccountPda, findThawExtraMetasAccountPda, getFreezePermissionlessInstruction, getMintConfigDecoder, getThawPermissionlessInstruction } from './generated'; import { resolveExtraMetas } from '@mosaic/tlv-account-resolution'; diff --git a/packages/ebalts/tsconfig.json b/packages/ebalts/tsconfig.json index 01db065..f7d4c81 100644 --- a/packages/ebalts/tsconfig.json +++ b/packages/ebalts/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./dist", - "rootDir": "./src" + "verbatimModuleSyntax": false }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"], diff --git a/packages/sdk/src/abl/setExtraMetas.ts b/packages/sdk/src/abl/setExtraMetas.ts index ca8d99b..a7b7223 100644 --- a/packages/sdk/src/abl/setExtraMetas.ts +++ b/packages/sdk/src/abl/setExtraMetas.ts @@ -1,4 +1,4 @@ -import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { createTransaction, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; import { ABL_PROGRAM_ID } from "./utils"; import { getSetExtraMetasThawInstruction } from '@mosaic/abl'; import { findMintConfigPda, findThawExtraMetasAccountPda } from '@mosaic/ebalts'; diff --git a/packages/sdk/src/ebalts/createConfig.ts b/packages/sdk/src/ebalts/createConfig.ts index 7fc2320..50e3ab2 100644 --- a/packages/sdk/src/ebalts/createConfig.ts +++ b/packages/sdk/src/ebalts/createConfig.ts @@ -1,6 +1,4 @@ -import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; -import { ABL_PROGRAM_ID, getCreateListInstructions } from "../abl"; +import { createTransaction, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; import { findMintConfigPda, getCreateConfigInstruction } from "@mosaic/ebalts"; import { EBALTS_PROGRAM_ID } from "./utils"; diff --git a/packages/sdk/src/ebalts/enablePermissionlessThaw.ts b/packages/sdk/src/ebalts/enablePermissionlessThaw.ts index 63e186d..d546049 100644 --- a/packages/sdk/src/ebalts/enablePermissionlessThaw.ts +++ b/packages/sdk/src/ebalts/enablePermissionlessThaw.ts @@ -1,7 +1,5 @@ -import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; -import { ABL_PROGRAM_ID, getCreateListInstructions } from "../abl"; -import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction, getTogglePermissionlessInstructionsInstruction } from "@mosaic/ebalts"; +import { createTransaction, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { findMintConfigPda, getTogglePermissionlessInstructionsInstruction } from "@mosaic/ebalts"; import { EBALTS_PROGRAM_ID } from "./utils"; diff --git a/packages/sdk/src/ebalts/setGatingProgram.ts b/packages/sdk/src/ebalts/setGatingProgram.ts index 13ceab6..307d4e3 100644 --- a/packages/sdk/src/ebalts/setGatingProgram.ts +++ b/packages/sdk/src/ebalts/setGatingProgram.ts @@ -1,7 +1,5 @@ -import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; -import { ABL_PROGRAM_ID, getCreateListInstructions } from "../abl"; -import { findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction } from "@mosaic/ebalts"; +import { createTransaction, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { findMintConfigPda, getSetGatingProgramInstruction } from "@mosaic/ebalts"; import { EBALTS_PROGRAM_ID } from "./utils"; diff --git a/packages/sdk/src/ebalts/thawPermissionless.ts b/packages/sdk/src/ebalts/thawPermissionless.ts index 24cd93d..a93d0a9 100644 --- a/packages/sdk/src/ebalts/thawPermissionless.ts +++ b/packages/sdk/src/ebalts/thawPermissionless.ts @@ -1,9 +1,7 @@ -import { createTransaction, fetchEncodedAccount, generateKeyPairSigner, lamports, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; -import { ABL_PROGRAM_ID, getCreateListInstructions } from "../abl"; -import { createThawPermissionlessInstructionWithExtraMetas, findMintConfigPda, getCreateConfigInstruction, getSetGatingProgramInstruction } from "@mosaic/ebalts"; +import { createTransaction, fetchEncodedAccount, lamports, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; +import { createThawPermissionlessInstructionWithExtraMetas, findMintConfigPda } from "@mosaic/ebalts"; import { EBALTS_PROGRAM_ID } from "./utils"; -import { getTokenEncoder, AccountState, TOKEN_2022_PROGRAM_ADDRESS, AuthorityType } from "gill/programs"; +import { getTokenEncoder, AccountState, TOKEN_2022_PROGRAM_ADDRESS } from "gill/programs"; /** @@ -34,7 +32,7 @@ export const getThawPermissionlessInstructions = async (input: { const thawPermissionlessInstruction = await createThawPermissionlessInstructionWithExtraMetas(input.authority, input.tokenAccount, input.mint, mintConfigPda[0], input.tokenAccountOwner, EBALTS_PROGRAM_ID, async (address: Address) => { - let data = getTokenEncoder().encode({ + const data = getTokenEncoder().encode({ amount: 0, closeAuthority: null, delegate: null, diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json index 38fefa0..4b514cb 100644 --- a/packages/sdk/tsconfig.json +++ b/packages/sdk/tsconfig.json @@ -2,7 +2,6 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./dist", - "rootDir": "./src", "noEmit": false, "moduleResolution": "bundler" }, diff --git a/packages/tlv-account-resolution/src/pubkeyData.ts b/packages/tlv-account-resolution/src/pubkeyData.ts index ca98083..aad94ff 100644 --- a/packages/tlv-account-resolution/src/pubkeyData.ts +++ b/packages/tlv-account-resolution/src/pubkeyData.ts @@ -5,7 +5,7 @@ import { TokenTransferHookPubkeyDataTooSmall, TokenTransferHookAccountNotFound, } from './errors.js'; -import { type Address, type Rpc, type AccountMeta, fetchEncodedAccount, type GetAccountInfoApi, address, getAddressDecoder, type MaybeEncodedAccount } from '@solana/kit'; +import { type Address, type AccountMeta, getAddressDecoder, type MaybeEncodedAccount } from '@solana/kit'; export async function unpackPubkeyData( diff --git a/packages/tlv-account-resolution/src/seeds.ts b/packages/tlv-account-resolution/src/seeds.ts index 01711b1..f435cbd 100644 --- a/packages/tlv-account-resolution/src/seeds.ts +++ b/packages/tlv-account-resolution/src/seeds.ts @@ -1,12 +1,9 @@ import { TokenTransferHookAccountDataNotFound, - TokenTransferHookInvalidPubkeyData, - TokenTransferHookPubkeyDataTooSmall, - TokenTransferHookAccountNotFound, TokenTransferHookInvalidSeed, } from './errors.js'; -import { type Address, type Rpc, type AccountMeta, fetchEncodedAccount, type GetAccountInfoApi, address, getAddressDecoder, getAddressEncoder, type MaybeEncodedAccount } from '@solana/kit'; +import { type Address, type AccountMeta, getAddressEncoder, type MaybeEncodedAccount } from '@solana/kit'; interface Seed { data: Buffer; diff --git a/packages/tlv-account-resolution/src/state.ts b/packages/tlv-account-resolution/src/state.ts index b1cf6d7..2986e18 100644 --- a/packages/tlv-account-resolution/src/state.ts +++ b/packages/tlv-account-resolution/src/state.ts @@ -2,7 +2,7 @@ import { TokenTransferHookAccountNotFound, TokenTransferHookInvalidPubkeyData } from './errors.js'; import { unpackSeeds } from './seeds.js'; import { unpackPubkeyData } from './pubkeyData.js'; -import { type Address, type AccountMeta, type GetAccountInfoApi, type Rpc, getProgramDerivedAddress, address, AccountRole, mergeRoles, getAddressDecoder, type MaybeEncodedAccount } from '@solana/kit'; +import { type Address, type AccountMeta, getProgramDerivedAddress, AccountRole, mergeRoles, getAddressDecoder, type MaybeEncodedAccount } from '@solana/kit'; export async function resolveExtraMetas( @@ -58,7 +58,7 @@ export function unpackExtraAccountMetas( if (data.length < 12) { throw new TokenTransferHookInvalidPubkeyData(); } - const discriminator = data.slice(0,8); + //const discriminator = data.slice(0,8); const length = new DataView(data.buffer, 8, 4).getUint32(0, true); const count = new DataView(data.buffer, 12, 4).getUint32(0, true); const offset = 16; From 874374ad558f1dca5fd6af8ca180902513f7019e Mon Sep 17 00:00:00 2001 From: tiago Date: Thu, 31 Jul 2025 17:11:23 +0100 Subject: [PATCH 5/9] fmt --- packages/abl/codama.json | 18 +- packages/abl/idl/abl_srfc37.json | 202 ++------------- .../abl/src/generated/accounts/aBWallet.ts | 4 +- .../abl/src/generated/accounts/listConfig.ts | 4 +- .../generated/instructions/addWalletToList.ts | 2 +- .../instructions/canFreezePermissionless.ts | 2 +- .../instructions/canThawPermissionless.ts | 2 +- .../instructions/initializeListConfig.ts | 2 +- .../instructions/removeWalletFromList.ts | 2 +- .../instructions/setExtraMetasThaw.ts | 2 +- .../src/generated/instructions/setListMode.ts | 2 +- packages/abl/src/index.ts | 71 +++--- packages/cli/src/commands/abl/abl.ts | 2 +- packages/cli/src/commands/abl/createList.ts | 20 +- .../cli/src/commands/abl/setExtraMetas.ts | 20 +- packages/cli/src/commands/abl/utils.ts | 6 +- .../cli/src/commands/create/arcade-token.ts | 5 +- .../cli/src/commands/ebalts/createConfig.ts | 27 +- packages/cli/src/commands/ebalts/ebalts.ts | 2 +- .../ebalts/enablePermissionlessThaw.ts | 20 +- .../src/commands/ebalts/setGatingProgram.ts | 38 +-- .../src/commands/ebalts/thawPermissionless.ts | 19 +- packages/cli/src/commands/ebalts/util.ts | 6 +- packages/cli/src/index.ts | 2 +- .../src/generated/accounts/mintConfig.ts | 4 +- .../generated/instructions/createConfig.ts | 2 +- .../instructions/forfeitFreezeAuthority.ts | 2 +- .../src/generated/instructions/freeze.ts | 2 +- .../instructions/freezePermissionless.ts | 2 +- .../generated/instructions/setAuthority.ts | 2 +- .../instructions/setGatingProgram.ts | 2 +- .../ebalts/src/generated/instructions/thaw.ts | 2 +- .../instructions/thawPermissionless.ts | 2 +- .../togglePermissionlessInstructions.ts | 2 +- packages/ebalts/src/index.ts | 208 ++++++++------- packages/sdk/src/abl/createList.ts | 108 ++++---- packages/sdk/src/abl/index.ts | 2 +- packages/sdk/src/abl/setExtraMetas.ts | 107 +++++--- packages/sdk/src/abl/utils.ts | 7 +- packages/sdk/src/ebalts/createConfig.ts | 121 +++++---- .../src/ebalts/enablePermissionlessThaw.ts | 94 ++++--- packages/sdk/src/ebalts/index.ts | 4 +- packages/sdk/src/ebalts/setGatingProgram.ts | 108 ++++---- packages/sdk/src/ebalts/thawPermissionless.ts | 164 +++++++----- packages/sdk/src/ebalts/utils.ts | 7 +- packages/sdk/src/index.ts | 2 +- packages/sdk/src/issuance/createMint.ts | 4 +- packages/tlv-account-resolution/src/errors.ts | 42 +-- packages/tlv-account-resolution/src/index.ts | 2 +- .../tlv-account-resolution/src/pubkeyData.ts | 114 +++++---- packages/tlv-account-resolution/src/seeds.ts | 217 +++++++++------- packages/tlv-account-resolution/src/state.ts | 240 ++++++++++-------- tsconfig.json | 4 +- 53 files changed, 1069 insertions(+), 988 deletions(-) diff --git a/packages/abl/codama.json b/packages/abl/codama.json index ec13733..a2c5b6b 100644 --- a/packages/abl/codama.json +++ b/packages/abl/codama.json @@ -1,12 +1,10 @@ { - "idl": "idl/abl_srfc37.json", - "before": [], - "scripts": { - "js": { - "from": "@codama/renderers-js", - "args": [ - "src/generated/" - ] - } + "idl": "idl/abl_srfc37.json", + "before": [], + "scripts": { + "js": { + "from": "@codama/renderers-js", + "args": ["src/generated/"] } -} \ No newline at end of file + } +} diff --git a/packages/abl/idl/abl_srfc37.json b/packages/abl/idl/abl_srfc37.json index 3f6e7d0..a221e94 100644 --- a/packages/abl/idl/abl_srfc37.json +++ b/packages/abl/idl/abl_srfc37.json @@ -9,24 +9,13 @@ "instructions": [ { "name": "add_wallet_to_list", - "discriminator": [ - 249, - 25, - 0, - 35, - 88, - 124, - 60, - 201 - ], + "discriminator": [249, 25, 0, 35, 88, 124, 60, 201], "accounts": [ { "name": "authority", "writable": true, "signer": true, - "relations": [ - "list_config" - ] + "relations": ["list_config"] }, { "name": "list_config" @@ -62,31 +51,13 @@ }, { "name": "can_freeze_permissionless", - "discriminator": [ - 214, - 141, - 109, - 75, - 248, - 1, - 45, - 29 - ], + "discriminator": [214, 141, 109, 75, 248, 1, 45, 29], "accounts": [], "args": [] }, { "name": "can_thaw_permissionless", - "discriminator": [ - 8, - 175, - 169, - 129, - 137, - 74, - 61, - 241 - ], + "discriminator": [8, 175, 169, 129, 137, 74, 61, 241], "accounts": [ { "name": "authority" @@ -114,16 +85,7 @@ }, { "name": "initialize_list_config", - "discriminator": [ - 201, - 223, - 17, - 210, - 208, - 124, - 101, - 58 - ], + "discriminator": [201, 223, 17, 210, 208, 124, 101, 58], "accounts": [ { "name": "authority", @@ -137,19 +99,7 @@ "seeds": [ { "kind": "const", - "value": [ - 108, - 105, - 115, - 116, - 95, - 99, - 111, - 110, - 102, - 105, - 103 - ] + "value": [108, 105, 115, 116, 95, 99, 111, 110, 102, 105, 103] }, { "kind": "account", @@ -180,24 +130,13 @@ }, { "name": "remove_wallet_from_list", - "discriminator": [ - 185, - 14, - 13, - 222, - 207, - 118, - 221, - 146 - ], + "discriminator": [185, 14, 13, 222, 207, 118, 221, 146], "accounts": [ { "name": "authority", "writable": true, "signer": true, - "relations": [ - "list_config" - ] + "relations": ["list_config"] }, { "name": "list_config" @@ -229,16 +168,7 @@ }, { "name": "set_extra_metas_thaw", - "discriminator": [ - 6, - 94, - 201, - 255, - 159, - 241, - 169, - 164 - ], + "discriminator": [6, 94, 201, 255, 159, 241, 169, 164], "accounts": [ { "name": "authority", @@ -254,19 +184,7 @@ "seeds": [ { "kind": "const", - "value": [ - 77, - 73, - 78, - 84, - 95, - 67, - 79, - 78, - 70, - 73, - 71 - ] + "value": [77, 73, 78, 84, 95, 67, 79, 78, 70, 73, 71] }, { "kind": "account", @@ -276,38 +194,9 @@ "program": { "kind": "const", "value": [ - 202, - 3, - 2, - 25, - 133, - 31, - 219, - 239, - 24, - 84, - 179, - 198, - 92, - 76, - 228, - 172, - 204, - 14, - 138, - 90, - 35, - 151, - 49, - 178, - 41, - 166, - 250, - 0, - 0, - 0, - 0, - 0 + 202, 3, 2, 25, 133, 31, 219, 239, 24, 84, 179, 198, 92, 76, 228, + 172, 204, 14, 138, 90, 35, 151, 49, 178, 41, 166, 250, 0, 0, 0, + 0, 0 ] } } @@ -323,30 +212,8 @@ { "kind": "const", "value": [ - 116, - 104, - 97, - 119, - 95, - 101, - 120, - 116, - 114, - 97, - 95, - 97, - 99, - 99, - 111, - 117, - 110, - 116, - 95, - 109, - 101, - 116, - 97, - 115 + 116, 104, 97, 119, 95, 101, 120, 116, 114, 97, 95, 97, 99, 99, + 111, 117, 110, 116, 95, 109, 101, 116, 97, 115 ] }, { @@ -365,24 +232,13 @@ }, { "name": "set_list_mode", - "discriminator": [ - 174, - 19, - 169, - 240, - 19, - 9, - 146, - 12 - ], + "discriminator": [174, 19, 169, 240, 19, 9, 146, 12], "accounts": [ { "name": "authority", "writable": true, "signer": true, - "relations": [ - "list_config" - ] + "relations": ["list_config"] }, { "name": "list_config" @@ -403,29 +259,11 @@ "accounts": [ { "name": "ABWallet", - "discriminator": [ - 111, - 162, - 31, - 45, - 79, - 239, - 198, - 72 - ] + "discriminator": [111, 162, 31, 45, 79, 239, 198, 72] }, { "name": "ListConfig", - "discriminator": [ - 9, - 220, - 3, - 74, - 122, - 218, - 71, - 204 - ] + "discriminator": [9, 220, 3, 74, 122, 218, 71, 204] } ], "errors": [ @@ -529,4 +367,4 @@ } } ] -} \ No newline at end of file +} diff --git a/packages/abl/src/generated/accounts/aBWallet.ts b/packages/abl/src/generated/accounts/aBWallet.ts index ea12b48..7c3241f 100644 --- a/packages/abl/src/generated/accounts/aBWallet.ts +++ b/packages/abl/src/generated/accounts/aBWallet.ts @@ -53,7 +53,7 @@ export function getABWalletEncoder(): FixedSizeEncoder { ['discriminator', fixEncoderSize(getBytesEncoder(), 8)], ['wallet', getAddressEncoder()], ]), - (value) => ({ ...value, discriminator: A_B_WALLET_DISCRIMINATOR }) + value => ({ ...value, discriminator: A_B_WALLET_DISCRIMINATOR }) ); } @@ -118,7 +118,7 @@ export async function fetchAllMaybeABWallet( config?: FetchAccountsConfig ): Promise[]> { const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config); - return maybeAccounts.map((maybeAccount) => decodeABWallet(maybeAccount)); + return maybeAccounts.map(maybeAccount => decodeABWallet(maybeAccount)); } export function getABWalletSize(): number { diff --git a/packages/abl/src/generated/accounts/listConfig.ts b/packages/abl/src/generated/accounts/listConfig.ts index 5e2b9e3..aa9a98a 100644 --- a/packages/abl/src/generated/accounts/listConfig.ts +++ b/packages/abl/src/generated/accounts/listConfig.ts @@ -75,7 +75,7 @@ export function getListConfigEncoder(): FixedSizeEncoder { ['mode', getModeEncoder()], ['bump', getU8Encoder()], ]), - (value) => ({ ...value, discriminator: LIST_CONFIG_DISCRIMINATOR }) + value => ({ ...value, discriminator: LIST_CONFIG_DISCRIMINATOR }) ); } @@ -146,7 +146,7 @@ export async function fetchAllMaybeListConfig( config?: FetchAccountsConfig ): Promise[]> { const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config); - return maybeAccounts.map((maybeAccount) => decodeListConfig(maybeAccount)); + return maybeAccounts.map(maybeAccount => decodeListConfig(maybeAccount)); } export function getListConfigSize(): number { diff --git a/packages/abl/src/generated/instructions/addWalletToList.ts b/packages/abl/src/generated/instructions/addWalletToList.ts index 510027d..53deb9b 100644 --- a/packages/abl/src/generated/instructions/addWalletToList.ts +++ b/packages/abl/src/generated/instructions/addWalletToList.ts @@ -88,7 +88,7 @@ export function getAddWalletToListInstructionDataEncoder(): FixedSizeEncoder ({ ...value, discriminator: ADD_WALLET_TO_LIST_DISCRIMINATOR }) + value => ({ ...value, discriminator: ADD_WALLET_TO_LIST_DISCRIMINATOR }) ); } diff --git a/packages/abl/src/generated/instructions/canFreezePermissionless.ts b/packages/abl/src/generated/instructions/canFreezePermissionless.ts index 83c655f..f1fa922 100644 --- a/packages/abl/src/generated/instructions/canFreezePermissionless.ts +++ b/packages/abl/src/generated/instructions/canFreezePermissionless.ts @@ -53,7 +53,7 @@ export type CanFreezePermissionlessInstructionDataArgs = {}; export function getCanFreezePermissionlessInstructionDataEncoder(): FixedSizeEncoder { return transformEncoder( getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), - (value) => ({ + value => ({ ...value, discriminator: CAN_FREEZE_PERMISSIONLESS_DISCRIMINATOR, }) diff --git a/packages/abl/src/generated/instructions/canThawPermissionless.ts b/packages/abl/src/generated/instructions/canThawPermissionless.ts index dd8a119..abf7e0d 100644 --- a/packages/abl/src/generated/instructions/canThawPermissionless.ts +++ b/packages/abl/src/generated/instructions/canThawPermissionless.ts @@ -87,7 +87,7 @@ export type CanThawPermissionlessInstructionDataArgs = {}; export function getCanThawPermissionlessInstructionDataEncoder(): FixedSizeEncoder { return transformEncoder( getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), - (value) => ({ + value => ({ ...value, discriminator: CAN_THAW_PERMISSIONLESS_DISCRIMINATOR, }) diff --git a/packages/abl/src/generated/instructions/initializeListConfig.ts b/packages/abl/src/generated/instructions/initializeListConfig.ts index 605ebe3..acd0b11 100644 --- a/packages/abl/src/generated/instructions/initializeListConfig.ts +++ b/packages/abl/src/generated/instructions/initializeListConfig.ts @@ -95,7 +95,7 @@ export function getInitializeListConfigInstructionDataEncoder(): FixedSizeEncode ['seed', getAddressEncoder()], ['mode', getModeEncoder()], ]), - (value) => ({ + value => ({ ...value, discriminator: INITIALIZE_LIST_CONFIG_DISCRIMINATOR, }) diff --git a/packages/abl/src/generated/instructions/removeWalletFromList.ts b/packages/abl/src/generated/instructions/removeWalletFromList.ts index e6011c7..b7c474c 100644 --- a/packages/abl/src/generated/instructions/removeWalletFromList.ts +++ b/packages/abl/src/generated/instructions/removeWalletFromList.ts @@ -82,7 +82,7 @@ export type RemoveWalletFromListInstructionDataArgs = {}; export function getRemoveWalletFromListInstructionDataEncoder(): FixedSizeEncoder { return transformEncoder( getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), - (value) => ({ + value => ({ ...value, discriminator: REMOVE_WALLET_FROM_LIST_DISCRIMINATOR, }) diff --git a/packages/abl/src/generated/instructions/setExtraMetasThaw.ts b/packages/abl/src/generated/instructions/setExtraMetasThaw.ts index 8cdde8e..feca781 100644 --- a/packages/abl/src/generated/instructions/setExtraMetasThaw.ts +++ b/packages/abl/src/generated/instructions/setExtraMetasThaw.ts @@ -96,7 +96,7 @@ export type SetExtraMetasThawInstructionDataArgs = {}; export function getSetExtraMetasThawInstructionDataEncoder(): FixedSizeEncoder { return transformEncoder( getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), - (value) => ({ ...value, discriminator: SET_EXTRA_METAS_THAW_DISCRIMINATOR }) + value => ({ ...value, discriminator: SET_EXTRA_METAS_THAW_DISCRIMINATOR }) ); } diff --git a/packages/abl/src/generated/instructions/setListMode.ts b/packages/abl/src/generated/instructions/setListMode.ts index 2445a64..aca962d 100644 --- a/packages/abl/src/generated/instructions/setListMode.ts +++ b/packages/abl/src/generated/instructions/setListMode.ts @@ -81,7 +81,7 @@ export function getSetListModeInstructionDataEncoder(): FixedSizeEncoder ({ ...value, discriminator: SET_LIST_MODE_DISCRIMINATOR }) + value => ({ ...value, discriminator: SET_LIST_MODE_DISCRIMINATOR }) ); } diff --git a/packages/abl/src/index.ts b/packages/abl/src/index.ts index 7c8ec4b..a149f3f 100644 --- a/packages/abl/src/index.ts +++ b/packages/abl/src/index.ts @@ -1,53 +1,52 @@ - import { - getAddressEncoder, - getProgramDerivedAddress, - getUtf8Encoder, - type Address, - type ProgramDerivedAddress, + getAddressEncoder, + getProgramDerivedAddress, + getUtf8Encoder, + type Address, + type ProgramDerivedAddress, } from '@solana/kit'; export type ListConfigSeeds = { - authority: Address; - seed: Address; + authority: Address; + seed: Address; }; export async function findListConfigPda( - seeds: ListConfigSeeds, - config: { programAddress?: Address | undefined } = {} + seeds: ListConfigSeeds, + config: { programAddress?: Address | undefined } = {} ): Promise { - const { - programAddress = 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, - } = config; - return await getProgramDerivedAddress({ - programAddress, - seeds: [ - getUtf8Encoder().encode('list_config'), - getAddressEncoder().encode(seeds.authority), - getAddressEncoder().encode(seeds.seed), - ], - }); + const { + programAddress = 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, + } = config; + return await getProgramDerivedAddress({ + programAddress, + seeds: [ + getUtf8Encoder().encode('list_config'), + getAddressEncoder().encode(seeds.authority), + getAddressEncoder().encode(seeds.seed), + ], + }); } export type ABWalletSeeds = { - wallet: Address; - list: Address; + wallet: Address; + list: Address; }; export async function findABWalletPda( - seeds: ABWalletSeeds, - config: { programAddress?: Address | undefined } = {} + seeds: ABWalletSeeds, + config: { programAddress?: Address | undefined } = {} ): Promise { - const { - programAddress = 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, - } = config; - return await getProgramDerivedAddress({ - programAddress, - seeds: [ - getAddressEncoder().encode(seeds.list), - getAddressEncoder().encode(seeds.wallet), - ], - }); + const { + programAddress = 'Eba1ts11111111111111111111111111111111111111' as Address<'Eba1ts11111111111111111111111111111111111111'>, + } = config; + return await getProgramDerivedAddress({ + programAddress, + seeds: [ + getAddressEncoder().encode(seeds.list), + getAddressEncoder().encode(seeds.wallet), + ], + }); } -export * from './generated'; \ No newline at end of file +export * from './generated'; diff --git a/packages/cli/src/commands/abl/abl.ts b/packages/cli/src/commands/abl/abl.ts index 6e7cf88..4dcea78 100644 --- a/packages/cli/src/commands/abl/abl.ts +++ b/packages/cli/src/commands/abl/abl.ts @@ -4,4 +4,4 @@ import { setExtraMetas } from './setExtraMetas.js'; export const ablCommand = new Command('abl') .addCommand(createList) - .addCommand(setExtraMetas); \ No newline at end of file + .addCommand(setExtraMetas); diff --git a/packages/cli/src/commands/abl/createList.ts b/packages/cli/src/commands/abl/createList.ts index 280ec36..3cc8025 100644 --- a/packages/cli/src/commands/abl/createList.ts +++ b/packages/cli/src/commands/abl/createList.ts @@ -4,9 +4,7 @@ import ora from 'ora'; import { getCreateListTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; -import { - signTransactionMessageWithSigners, -} from 'gill'; +import { signTransactionMessageWithSigners } from 'gill'; interface CreateConfigOptions { mint: string; @@ -26,14 +24,12 @@ export const createList = new Command('create-list') const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); - - const {transaction, listConfig} = await getCreateListTransaction({ + const { transaction, listConfig } = await getCreateListTransaction({ rpc, payer: kp, authority: kp, }); - spinner.text = 'Signing transaction...'; // Sign the transaction @@ -43,7 +39,10 @@ export const createList = new Command('create-list') spinner.text = 'Sending transaction...'; // Send and confirm transaction - const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + const signature = await sendAndConfirmTransaction(signedTransaction, { + skipPreflight: true, + commitment: 'confirmed', + }); spinner.succeed('ABL list created successfully!'); @@ -52,14 +51,13 @@ export const createList = new Command('create-list') console.log(chalk.cyan('📋 Details:')); console.log(` ${chalk.bold('List Config:')} ${listConfig}`); console.log(` ${chalk.bold('Transaction:')} ${signature}`); - } - catch (error) { + } catch (error) { spinner.fail('Failed to create ABL list'); console.error( chalk.red('❌ Error:'), error instanceof Error ? error.message : 'Unknown error' ); - + process.exit(1); } - }); \ No newline at end of file + }); diff --git a/packages/cli/src/commands/abl/setExtraMetas.ts b/packages/cli/src/commands/abl/setExtraMetas.ts index a2c50ce..69390b1 100644 --- a/packages/cli/src/commands/abl/setExtraMetas.ts +++ b/packages/cli/src/commands/abl/setExtraMetas.ts @@ -4,10 +4,7 @@ import ora from 'ora'; import { getSetExtraMetasTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; -import { - signTransactionMessageWithSigners, - type Address, -} from 'gill'; +import { signTransactionMessageWithSigners, type Address } from 'gill'; interface CreateConfigOptions { mint: string; @@ -29,7 +26,7 @@ export const setExtraMetas = new Command('set-extra-metas') const keypairPath = options.keypair || parentOpts.keypair; const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(keypairPath); - + const transaction = await getSetExtraMetasTransaction({ rpc, payer: kp, @@ -38,7 +35,6 @@ export const setExtraMetas = new Command('set-extra-metas') list: options.list as Address, }); - spinner.text = 'Signing transaction...'; // Sign the transaction @@ -48,7 +44,10 @@ export const setExtraMetas = new Command('set-extra-metas') spinner.text = 'Sending transaction...'; // Send and confirm transaction - const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + const signature = await sendAndConfirmTransaction(signedTransaction, { + skipPreflight: true, + commitment: 'confirmed', + }); spinner.succeed('Extra metas set successfully!'); @@ -56,14 +55,13 @@ export const setExtraMetas = new Command('set-extra-metas') console.log(chalk.green('✅ Extra metas set successfully!')); console.log(chalk.cyan('📋 Details:')); console.log(` ${chalk.bold('Transaction:')} ${signature}`); - } - catch (error) { + } catch (error) { spinner.fail('Failed to set extra metas'); console.error( chalk.red('❌ Error:'), error instanceof Error ? error.message : 'Unknown error' ); - + process.exit(1); } - }); \ No newline at end of file + }); diff --git a/packages/cli/src/commands/abl/utils.ts b/packages/cli/src/commands/abl/utils.ts index be68de0..e4723b8 100644 --- a/packages/cli/src/commands/abl/utils.ts +++ b/packages/cli/src/commands/abl/utils.ts @@ -1,4 +1,4 @@ -import type { Address } from "gill"; +import type { Address } from 'gill'; - -export const ABL_PROGRAM_ID = '8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N' as Address; \ No newline at end of file +export const ABL_PROGRAM_ID = + '8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N' as Address; diff --git a/packages/cli/src/commands/create/arcade-token.ts b/packages/cli/src/commands/create/arcade-token.ts index f9d5235..66f7764 100644 --- a/packages/cli/src/commands/create/arcade-token.ts +++ b/packages/cli/src/commands/create/arcade-token.ts @@ -123,7 +123,10 @@ export const createArcadeTokenCommand = new Command('arcade-token') spinner.text = 'Sending transaction...'; // Send and confirm transaction - const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + const signature = await sendAndConfirmTransaction(signedTransaction, { + skipPreflight: true, + commitment: 'confirmed', + }); spinner.succeed('Arcade token created successfully!'); diff --git a/packages/cli/src/commands/ebalts/createConfig.ts b/packages/cli/src/commands/ebalts/createConfig.ts index c0934ec..7242c2d 100644 --- a/packages/cli/src/commands/ebalts/createConfig.ts +++ b/packages/cli/src/commands/ebalts/createConfig.ts @@ -4,10 +4,7 @@ import ora from 'ora'; import { getCreateConfigTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; -import { - signTransactionMessageWithSigners, - type Address, -} from 'gill'; +import { signTransactionMessageWithSigners, type Address } from 'gill'; interface CreateConfigOptions { mint: string; @@ -29,9 +26,10 @@ export const createConfig = new Command('create') const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); - const gatingProgram = (options.gatingProgram || '11111111111111111111111111111111') as Address; + const gatingProgram = (options.gatingProgram || + '11111111111111111111111111111111') as Address; - const {transaction, mintConfig} = await getCreateConfigTransaction({ + const { transaction, mintConfig } = await getCreateConfigTransaction({ rpc, payer: kp, authority: kp, @@ -39,7 +37,6 @@ export const createConfig = new Command('create') gatingProgram, }); - spinner.text = 'Signing transaction...'; // Sign the transaction @@ -49,7 +46,10 @@ export const createConfig = new Command('create') spinner.text = 'Sending transaction...'; // Send and confirm transaction - const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + const signature = await sendAndConfirmTransaction(signedTransaction, { + skipPreflight: true, + commitment: 'confirmed', + }); spinner.succeed('Ebalts config created successfully!'); @@ -57,17 +57,18 @@ export const createConfig = new Command('create') console.log(chalk.green('✅ Ebalts config created successfully!')); console.log(chalk.cyan('📋 Details:')); console.log(` ${chalk.bold('Mint:')} ${options.mint}`); - console.log(` ${chalk.bold('Gating Program:')} ${options.gatingProgram}`); + console.log( + ` ${chalk.bold('Gating Program:')} ${options.gatingProgram}` + ); console.log(` ${chalk.bold('Mint Config:')} ${mintConfig}`); console.log(` ${chalk.bold('Transaction:')} ${signature}`); - } - catch (error) { + } catch (error) { spinner.fail('Failed to create ebalts config'); console.error( chalk.red('❌ Error:'), error instanceof Error ? error.message : 'Unknown error' ); - + process.exit(1); } - }); \ No newline at end of file + }); diff --git a/packages/cli/src/commands/ebalts/ebalts.ts b/packages/cli/src/commands/ebalts/ebalts.ts index 1db6058..2009519 100644 --- a/packages/cli/src/commands/ebalts/ebalts.ts +++ b/packages/cli/src/commands/ebalts/ebalts.ts @@ -8,4 +8,4 @@ export const ebaltsCommand = new Command('ebalts') .addCommand(createConfig) .addCommand(setGatingProgram) .addCommand(thawPermissionless) - .addCommand(enablePermissionlessThaw); \ No newline at end of file + .addCommand(enablePermissionlessThaw); diff --git a/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts index 86c11b6..5d512bb 100644 --- a/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts +++ b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts @@ -4,10 +4,7 @@ import ora from 'ora'; import { getEnablePermissionlessThawTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; -import { - signTransactionMessageWithSigners, - type Address, -} from 'gill'; +import { signTransactionMessageWithSigners, type Address } from 'gill'; interface CreateConfigOptions { mint: string; @@ -16,7 +13,9 @@ interface CreateConfigOptions { keypair?: string; } -export const enablePermissionlessThaw = new Command('enable-permissionless-thaw') +export const enablePermissionlessThaw = new Command( + 'enable-permissionless-thaw' +) .description('Enable permissionless thaw for an existing mint') .requiredOption('-m, --mint ', 'Mint address') .action(async (options: CreateConfigOptions, command) => { @@ -37,7 +36,6 @@ export const enablePermissionlessThaw = new Command('enable-permissionless-thaw' mint: options.mint as Address, }); - spinner.text = 'Signing transaction...'; // Sign the transaction @@ -47,7 +45,10 @@ export const enablePermissionlessThaw = new Command('enable-permissionless-thaw' spinner.text = 'Sending transaction...'; // Send and confirm transaction - const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + const signature = await sendAndConfirmTransaction(signedTransaction, { + skipPreflight: true, + commitment: 'confirmed', + }); spinner.succeed('Permissionless thaw enabled successfully!'); @@ -56,8 +57,7 @@ export const enablePermissionlessThaw = new Command('enable-permissionless-thaw' console.log(chalk.cyan('📋 Details:')); console.log(` ${chalk.bold('Mint:')} ${options.mint}`); console.log(` ${chalk.bold('Transaction:')} ${signature}`); - } - catch (error) { + } catch (error) { spinner.fail('Failed to enable permissionless thaw'); console.error( chalk.red('❌ Error:'), @@ -65,4 +65,4 @@ export const enablePermissionlessThaw = new Command('enable-permissionless-thaw' ); process.exit(1); } - }); \ No newline at end of file + }); diff --git a/packages/cli/src/commands/ebalts/setGatingProgram.ts b/packages/cli/src/commands/ebalts/setGatingProgram.ts index 7b09883..92b2f22 100644 --- a/packages/cli/src/commands/ebalts/setGatingProgram.ts +++ b/packages/cli/src/commands/ebalts/setGatingProgram.ts @@ -1,13 +1,10 @@ import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; -import { getSetGatingProgramTransaction } from '@mosaic/sdk'; +import { getSetGatingProgramTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; -import { - signTransactionMessageWithSigners, - type Address, -} from 'gill'; +import { signTransactionMessageWithSigners, type Address } from 'gill'; import { findMintConfigPda } from '@mosaic/ebalts'; import { EBALTS_PROGRAM_ID } from './util.js'; @@ -21,7 +18,10 @@ interface CreateConfigOptions { export const setGatingProgram = new Command('set-gating-program') .description('Set the gating program for an existing mint') .requiredOption('-m, --mint ', 'Mint address') - .requiredOption('-g, --gating-program ', 'Gating program address') + .requiredOption( + '-g, --gating-program ', + 'Gating program address' + ) .action(async (options: CreateConfigOptions, command) => { const spinner = ora('Setting gating program...').start(); @@ -31,9 +31,13 @@ export const setGatingProgram = new Command('set-gating-program') const { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); const kp = await loadKeypair(options.keypair); - const mintConfigPda = await findMintConfigPda({ mint: options.mint as Address }, { programAddress: EBALTS_PROGRAM_ID }); - const gatingProgram = (options.gatingProgram || '11111111111111111111111111111111') as Address; - + const mintConfigPda = await findMintConfigPda( + { mint: options.mint as Address }, + { programAddress: EBALTS_PROGRAM_ID } + ); + const gatingProgram = (options.gatingProgram || + '11111111111111111111111111111111') as Address; + const transaction = await getSetGatingProgramTransaction({ rpc, payer: kp, @@ -51,7 +55,10 @@ export const setGatingProgram = new Command('set-gating-program') spinner.text = 'Sending transaction...'; // Send and confirm transaction - const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + const signature = await sendAndConfirmTransaction(signedTransaction, { + skipPreflight: true, + commitment: 'confirmed', + }); spinner.succeed('Gating program set successfully!'); @@ -59,17 +66,18 @@ export const setGatingProgram = new Command('set-gating-program') console.log(chalk.green('✅ Gating program set successfully!')); console.log(chalk.cyan('📋 Details:')); console.log(` ${chalk.bold('Mint:')} ${options.mint}`); - console.log(` ${chalk.bold('Gating Program:')} ${options.gatingProgram}`); + console.log( + ` ${chalk.bold('Gating Program:')} ${options.gatingProgram}` + ); console.log(` ${chalk.bold('Mint Config:')} ${mintConfigPda[0]}`); console.log(` ${chalk.bold('Transaction:')} ${signature}`); - } - catch (error) { + } catch (error) { spinner.fail('Failed to set gating program'); console.error( chalk.red('❌ Error:'), error instanceof Error ? error.message : 'Unknown error' ); - + process.exit(1); } - }); \ No newline at end of file + }); diff --git a/packages/cli/src/commands/ebalts/thawPermissionless.ts b/packages/cli/src/commands/ebalts/thawPermissionless.ts index 66c7c11..e9cb848 100644 --- a/packages/cli/src/commands/ebalts/thawPermissionless.ts +++ b/packages/cli/src/commands/ebalts/thawPermissionless.ts @@ -4,11 +4,11 @@ import ora from 'ora'; import { getThawPermissionlessTransaction } from '@mosaic/sdk'; import { createSolanaClient } from '../../utils/rpc.js'; import { loadKeypair } from '../../utils/solana.js'; +import { signTransactionMessageWithSigners, type Address } from 'gill'; import { - signTransactionMessageWithSigners, - type Address, -} from 'gill'; -import { getAssociatedTokenAccountAddress, TOKEN_2022_PROGRAM_ADDRESS } from 'gill/programs/token'; + getAssociatedTokenAccountAddress, + TOKEN_2022_PROGRAM_ADDRESS, +} from 'gill/programs/token'; interface CreateConfigOptions { mint: string; @@ -51,7 +51,6 @@ export const thawPermissionless = new Command('thaw-permissionless') tokenAccountOwner: signerAddress, }); - spinner.text = 'Signing transaction...'; // Sign the transaction @@ -61,7 +60,10 @@ export const thawPermissionless = new Command('thaw-permissionless') spinner.text = 'Sending transaction...'; // Send and confirm transaction - const signature = await sendAndConfirmTransaction(signedTransaction, { skipPreflight: true, commitment: 'confirmed'}); + const signature = await sendAndConfirmTransaction(signedTransaction, { + skipPreflight: true, + commitment: 'confirmed', + }); spinner.succeed('Permissionless thawed successfully!'); @@ -70,8 +72,7 @@ export const thawPermissionless = new Command('thaw-permissionless') console.log(chalk.cyan('📋 Details:')); console.log(` ${chalk.bold('Token Account:')} ${ata}`); console.log(` ${chalk.bold('Transaction:')} ${signature}`); - } - catch (error) { + } catch (error) { spinner.fail('Failed to thaw permissionless'); console.error( chalk.red('❌ Error:'), @@ -80,4 +81,4 @@ export const thawPermissionless = new Command('thaw-permissionless') process.exit(1); } - }); \ No newline at end of file + }); diff --git a/packages/cli/src/commands/ebalts/util.ts b/packages/cli/src/commands/ebalts/util.ts index 9cdcc46..d451cff 100644 --- a/packages/cli/src/commands/ebalts/util.ts +++ b/packages/cli/src/commands/ebalts/util.ts @@ -1,4 +1,4 @@ -import type { Address } from "gill"; +import type { Address } from 'gill'; - -export const EBALTS_PROGRAM_ID = '81H44JYqk1p8RUks7pNJjhQG4Pj8FcaJeTUxZKN3JfLc' as Address; \ No newline at end of file +export const EBALTS_PROGRAM_ID = + '81H44JYqk1p8RUks7pNJjhQG4Pj8FcaJeTUxZKN3JfLc' as Address; diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index c91ea2f..2c27aed 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -41,7 +41,7 @@ program .option('--rpc-url ', 'Solana RPC URL', 'https://api.devnet.solana.com') .option( '--keypair ', - 'Path to keypair file (defaults to Solana CLI default)', + 'Path to keypair file (defaults to Solana CLI default)' ); program.parse(process.argv); diff --git a/packages/ebalts/src/generated/accounts/mintConfig.ts b/packages/ebalts/src/generated/accounts/mintConfig.ts index d542e32..8377779 100644 --- a/packages/ebalts/src/generated/accounts/mintConfig.ts +++ b/packages/ebalts/src/generated/accounts/mintConfig.ts @@ -71,7 +71,7 @@ export function getMintConfigEncoder(): Encoder { ['enablePermissionlessThaw', getBooleanEncoder()], ['enablePermissionlessFreeze', getBooleanEncoder()], ]), - (value) => ({ ...value, discriminator: MINT_CONFIG_DISCRIMINATOR }) + value => ({ ...value, discriminator: MINT_CONFIG_DISCRIMINATOR }) ); } @@ -141,7 +141,7 @@ export async function fetchAllMaybeMintConfig( config?: FetchAccountsConfig ): Promise[]> { const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config); - return maybeAccounts.map((maybeAccount) => decodeMintConfig(maybeAccount)); + return maybeAccounts.map(maybeAccount => decodeMintConfig(maybeAccount)); } export function getMintConfigSize(): number { diff --git a/packages/ebalts/src/generated/instructions/createConfig.ts b/packages/ebalts/src/generated/instructions/createConfig.ts index efbcfae..83ef7a7 100644 --- a/packages/ebalts/src/generated/instructions/createConfig.ts +++ b/packages/ebalts/src/generated/instructions/createConfig.ts @@ -91,7 +91,7 @@ export function getCreateConfigInstructionDataEncoder(): Encoder ({ ...value, discriminator: CREATE_CONFIG_DISCRIMINATOR }) + value => ({ ...value, discriminator: CREATE_CONFIG_DISCRIMINATOR }) ); } diff --git a/packages/ebalts/src/generated/instructions/forfeitFreezeAuthority.ts b/packages/ebalts/src/generated/instructions/forfeitFreezeAuthority.ts index 3174bdf..1326164 100644 --- a/packages/ebalts/src/generated/instructions/forfeitFreezeAuthority.ts +++ b/packages/ebalts/src/generated/instructions/forfeitFreezeAuthority.ts @@ -83,7 +83,7 @@ export function getForfeitFreezeAuthorityInstructionDataEncoder(): Encoder ({ + value => ({ ...value, discriminator: FORFEIT_FREEZE_AUTHORITY_DISCRIMINATOR, }) diff --git a/packages/ebalts/src/generated/instructions/freeze.ts b/packages/ebalts/src/generated/instructions/freeze.ts index 1a9d819..f2aacae 100644 --- a/packages/ebalts/src/generated/instructions/freeze.ts +++ b/packages/ebalts/src/generated/instructions/freeze.ts @@ -77,7 +77,7 @@ export type FreezeInstructionDataArgs = {}; export function getFreezeInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([['discriminator', getU8Encoder()]]), - (value) => ({ ...value, discriminator: FREEZE_DISCRIMINATOR }) + value => ({ ...value, discriminator: FREEZE_DISCRIMINATOR }) ); } diff --git a/packages/ebalts/src/generated/instructions/freezePermissionless.ts b/packages/ebalts/src/generated/instructions/freezePermissionless.ts index 9ef47e8..e6f3c40 100644 --- a/packages/ebalts/src/generated/instructions/freezePermissionless.ts +++ b/packages/ebalts/src/generated/instructions/freezePermissionless.ts @@ -85,7 +85,7 @@ export type FreezePermissionlessInstructionDataArgs = {}; export function getFreezePermissionlessInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([['discriminator', getU8Encoder()]]), - (value) => ({ + value => ({ ...value, discriminator: FREEZE_PERMISSIONLESS_DISCRIMINATOR, }) diff --git a/packages/ebalts/src/generated/instructions/setAuthority.ts b/packages/ebalts/src/generated/instructions/setAuthority.ts index be78b4c..85193ce 100644 --- a/packages/ebalts/src/generated/instructions/setAuthority.ts +++ b/packages/ebalts/src/generated/instructions/setAuthority.ts @@ -70,7 +70,7 @@ export function getSetAuthorityInstructionDataEncoder(): Encoder ({ ...value, discriminator: SET_AUTHORITY_DISCRIMINATOR }) + value => ({ ...value, discriminator: SET_AUTHORITY_DISCRIMINATOR }) ); } diff --git a/packages/ebalts/src/generated/instructions/setGatingProgram.ts b/packages/ebalts/src/generated/instructions/setGatingProgram.ts index d857e4a..0eb6040 100644 --- a/packages/ebalts/src/generated/instructions/setGatingProgram.ts +++ b/packages/ebalts/src/generated/instructions/setGatingProgram.ts @@ -70,7 +70,7 @@ export function getSetGatingProgramInstructionDataEncoder(): Encoder ({ ...value, discriminator: SET_GATING_PROGRAM_DISCRIMINATOR }) + value => ({ ...value, discriminator: SET_GATING_PROGRAM_DISCRIMINATOR }) ); } diff --git a/packages/ebalts/src/generated/instructions/thaw.ts b/packages/ebalts/src/generated/instructions/thaw.ts index be59827..9e9ad13 100644 --- a/packages/ebalts/src/generated/instructions/thaw.ts +++ b/packages/ebalts/src/generated/instructions/thaw.ts @@ -77,7 +77,7 @@ export type ThawInstructionDataArgs = {}; export function getThawInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([['discriminator', getU8Encoder()]]), - (value) => ({ ...value, discriminator: THAW_DISCRIMINATOR }) + value => ({ ...value, discriminator: THAW_DISCRIMINATOR }) ); } diff --git a/packages/ebalts/src/generated/instructions/thawPermissionless.ts b/packages/ebalts/src/generated/instructions/thawPermissionless.ts index 65820dd..d413b65 100644 --- a/packages/ebalts/src/generated/instructions/thawPermissionless.ts +++ b/packages/ebalts/src/generated/instructions/thawPermissionless.ts @@ -85,7 +85,7 @@ export type ThawPermissionlessInstructionDataArgs = {}; export function getThawPermissionlessInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([['discriminator', getU8Encoder()]]), - (value) => ({ ...value, discriminator: THAW_PERMISSIONLESS_DISCRIMINATOR }) + value => ({ ...value, discriminator: THAW_PERMISSIONLESS_DISCRIMINATOR }) ); } diff --git a/packages/ebalts/src/generated/instructions/togglePermissionlessInstructions.ts b/packages/ebalts/src/generated/instructions/togglePermissionlessInstructions.ts index 1d1c278..829e50a 100644 --- a/packages/ebalts/src/generated/instructions/togglePermissionlessInstructions.ts +++ b/packages/ebalts/src/generated/instructions/togglePermissionlessInstructions.ts @@ -77,7 +77,7 @@ export function getTogglePermissionlessInstructionsInstructionDataEncoder(): Enc ['freezeEnabled', getBooleanEncoder()], ['thawEnabled', getBooleanEncoder()], ]), - (value) => ({ + value => ({ ...value, discriminator: TOGGLE_PERMISSIONLESS_INSTRUCTIONS_DISCRIMINATOR, }) diff --git a/packages/ebalts/src/index.ts b/packages/ebalts/src/index.ts index 849de23..375fd69 100644 --- a/packages/ebalts/src/index.ts +++ b/packages/ebalts/src/index.ts @@ -1,104 +1,140 @@ -import { type Address, type Instruction, type TransactionSigner, AccountRole, type AccountMeta, type MaybeEncodedAccount } from '@solana/kit'; +import { + type Address, + type Instruction, + type TransactionSigner, + AccountRole, + type AccountMeta, + type MaybeEncodedAccount, +} from '@solana/kit'; import { findMintConfigPda } from './generated/pdas/mintConfig'; -import { findFreezeExtraMetasAccountPda, findThawExtraMetasAccountPda, getFreezePermissionlessInstruction, getMintConfigDecoder, getThawPermissionlessInstruction } from './generated'; +import { + findFreezeExtraMetasAccountPda, + findThawExtraMetasAccountPda, + getFreezePermissionlessInstruction, + getMintConfigDecoder, + getThawPermissionlessInstruction, +} from './generated'; import { resolveExtraMetas } from '@mosaic/tlv-account-resolution'; export * from './generated'; export async function createThawPermissionlessInstructionWithExtraMetas( - authority: TransactionSigner, - tokenAccount: Address, - mint: Address, - mintConfig: Address, - tokenAccountOwner: Address, - programAddress: Address, - accountRetriever: (address: Address) => Promise>, + authority: TransactionSigner, + tokenAccount: Address, + mint: Address, + mintConfig: Address, + tokenAccountOwner: Address, + programAddress: Address, + accountRetriever: (address: Address) => Promise> ): Promise { - - const mintConfigPda = await findMintConfigPda({ mint }, { programAddress }); - const mintConfigAccount = await accountRetriever(mintConfigPda[0]); - if (!mintConfigAccount.exists) { - throw new Error('Mint config account not found'); - } - const mintConfigData = getMintConfigDecoder().decode(mintConfigAccount.data); - - const thawExtraMetas = await findThawExtraMetasAccountPda({ mint }, { programAddress: mintConfigData.gatingProgram }); - - console.log(mintConfigData); - console.log(thawExtraMetas[0]); - - - const canThawPermissionlessInstruction = getCanThawPermissionlessAccountMetas(authority.address, tokenAccount, mint, tokenAccountOwner, thawExtraMetas[0]); - - const thawAccountInstruction = getThawPermissionlessInstruction({ - authority, - tokenAccount, - mint, - mintConfig, - tokenAccountOwner, - gatingProgram: mintConfigData.gatingProgram, + const mintConfigPda = await findMintConfigPda({ mint }, { programAddress }); + const mintConfigAccount = await accountRetriever(mintConfigPda[0]); + if (!mintConfigAccount.exists) { + throw new Error('Mint config account not found'); + } + const mintConfigData = getMintConfigDecoder().decode(mintConfigAccount.data); + + const thawExtraMetas = await findThawExtraMetasAccountPda( + { mint }, + { programAddress: mintConfigData.gatingProgram } + ); + + console.log(mintConfigData); + console.log(thawExtraMetas[0]); + + const canThawPermissionlessInstruction = getCanThawPermissionlessAccountMetas( + authority.address, + tokenAccount, + mint, + tokenAccountOwner, + thawExtraMetas[0] + ); + + const thawAccountInstruction = getThawPermissionlessInstruction( + { + authority, + tokenAccount, + mint, + mintConfig, + tokenAccountOwner, + gatingProgram: mintConfigData.gatingProgram, }, { - programAddress - }); - - const metas = await resolveExtraMetas(accountRetriever, thawExtraMetas[0], canThawPermissionlessInstruction, Buffer.from(thawAccountInstruction.data), mintConfigData.gatingProgram); - - const ix = { - ...thawAccountInstruction, - accounts: [...thawAccountInstruction.accounts!, ...metas.slice(4)], + programAddress, } - return ix; + ); + + const metas = await resolveExtraMetas( + accountRetriever, + thawExtraMetas[0], + canThawPermissionlessInstruction, + Buffer.from(thawAccountInstruction.data), + mintConfigData.gatingProgram + ); + + const ix = { + ...thawAccountInstruction, + accounts: [...thawAccountInstruction.accounts!, ...metas.slice(4)], + }; + return ix; } function getCanThawPermissionlessAccountMetas( - authority: Address, - tokenAccount: Address, - mint: Address, - owner: Address, - extraMetasThaw: Address, + authority: Address, + tokenAccount: Address, + mint: Address, + owner: Address, + extraMetasThaw: Address ): AccountMeta[] { - return [ - { address: authority, role: AccountRole.READONLY }, - { address: tokenAccount, role: AccountRole.READONLY }, - { address: mint, role: AccountRole.READONLY }, - { address: owner, role: AccountRole.READONLY }, - { address: extraMetasThaw, role: AccountRole.READONLY }, - ] + return [ + { address: authority, role: AccountRole.READONLY }, + { address: tokenAccount, role: AccountRole.READONLY }, + { address: mint, role: AccountRole.READONLY }, + { address: owner, role: AccountRole.READONLY }, + { address: extraMetasThaw, role: AccountRole.READONLY }, + ]; } export async function createFreezePermissionlessInstructionWithExtraMetas( - authority: TransactionSigner, - tokenAccount: Address, - mint: Address, - mintConfig: Address, - tokenAccountOwner: Address, - accountRetriever: (address: Address) => Promise>, + authority: TransactionSigner, + tokenAccount: Address, + mint: Address, + mintConfig: Address, + tokenAccountOwner: Address, + accountRetriever: (address: Address) => Promise> ): Promise { - - const mintConfigPda = await findMintConfigPda({ mint }); - const mintConfigAccount = await accountRetriever(mintConfigPda[0]); - if (!mintConfigAccount.exists) { - throw new Error('Mint config account not found'); - } - const mintConfigData = getMintConfigDecoder().decode(mintConfigAccount.data); - - const freezeExtraMetas = await findFreezeExtraMetasAccountPda({ mint }, { programAddress: mintConfigData.gatingProgram }); - - const freezeAccountInstruction = getFreezePermissionlessInstruction({ - authority, - tokenAccount, - mint, - mintConfig, - tokenAccountOwner, - gatingProgram: mintConfigData.gatingProgram, - }); - - const metas = await resolveExtraMetas(accountRetriever, freezeExtraMetas[0], freezeAccountInstruction.accounts, Buffer.from(freezeAccountInstruction.data), mintConfigData.gatingProgram); - - const ix = { - ...freezeAccountInstruction, - accounts: metas, - } - return ix; -} \ No newline at end of file + const mintConfigPda = await findMintConfigPda({ mint }); + const mintConfigAccount = await accountRetriever(mintConfigPda[0]); + if (!mintConfigAccount.exists) { + throw new Error('Mint config account not found'); + } + const mintConfigData = getMintConfigDecoder().decode(mintConfigAccount.data); + + const freezeExtraMetas = await findFreezeExtraMetasAccountPda( + { mint }, + { programAddress: mintConfigData.gatingProgram } + ); + + const freezeAccountInstruction = getFreezePermissionlessInstruction({ + authority, + tokenAccount, + mint, + mintConfig, + tokenAccountOwner, + gatingProgram: mintConfigData.gatingProgram, + }); + + const metas = await resolveExtraMetas( + accountRetriever, + freezeExtraMetas[0], + freezeAccountInstruction.accounts, + Buffer.from(freezeAccountInstruction.data), + mintConfigData.gatingProgram + ); + + const ix = { + ...freezeAccountInstruction, + accounts: metas, + }; + return ix; +} diff --git a/packages/sdk/src/abl/createList.ts b/packages/sdk/src/abl/createList.ts index 56820f7..4a90d7c 100644 --- a/packages/sdk/src/abl/createList.ts +++ b/packages/sdk/src/abl/createList.ts @@ -1,48 +1,67 @@ -import { createTransaction, generateKeyPairSigner, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { ABL_PROGRAM_ID } from "./utils"; -import { findListConfigPda, getInitializeListConfigInstruction, Mode } from '@mosaic/abl'; - +import { + createTransaction, + generateKeyPairSigner, + type Address, + type FullTransaction, + type Instruction, + type Rpc, + type SolanaRpcApi, + type TransactionMessageWithFeePayer, + type TransactionSigner, + type TransactionVersion, + type TransactionWithBlockhashLifetime, +} from 'gill'; +import { ABL_PROGRAM_ID } from './utils'; +import { + findListConfigPda, + getInitializeListConfigInstruction, + Mode, +} from '@mosaic/abl'; /** * Generates instructions for creating a new allowlist/blocklist configuration. - * + * * This function creates the necessary instructions to initialize a list configuration * that can be used for gating token operations. The list can be configured as either * an allowlist or blocklist depending on the mode. - * + * * @param input - Configuration parameters for list creation * @param input.authority - The authority signer who will control the list configuration * @returns Promise containing the instructions and the list configuration address */ export const getCreateListInstructions = async (input: { - authority: TransactionSigner; - }): Promise<{instructions: Instruction[], listConfig: Address}> => { - const seed = await generateKeyPairSigner(); + authority: TransactionSigner; +}): Promise<{ instructions: Instruction[]; listConfig: Address }> => { + const seed = await generateKeyPairSigner(); - const listConfigPda = await findListConfigPda({ authority: input.authority.address, seed: seed.address }, { programAddress: ABL_PROGRAM_ID }); - + const listConfigPda = await findListConfigPda( + { authority: input.authority.address, seed: seed.address }, + { programAddress: ABL_PROGRAM_ID } + ); - const createListInstruction = getInitializeListConfigInstruction({ + const createListInstruction = getInitializeListConfigInstruction( + { authority: input.authority, listConfig: listConfigPda[0], mode: Mode.AllowWithPermissionlessEOAs, seed: seed.address, }, - { programAddress: ABL_PROGRAM_ID }); + { programAddress: ABL_PROGRAM_ID } + ); - return { - instructions: [createListInstruction], - listConfig: listConfigPda[0], - }; -} + return { + instructions: [createListInstruction], + listConfig: listConfigPda[0], + }; +}; /** * Creates a complete transaction for initializing a new allowlist/blocklist configuration. - * + * * This function builds a full transaction that can be signed and sent to create * a list configuration. The transaction includes the necessary instructions and * uses the latest blockhash for proper transaction construction. - * + * * @param input - Configuration parameters for the transaction * @param input.rpc - The Solana RPC client instance * @param input.payer - The transaction fee payer signer @@ -50,26 +69,29 @@ export const getCreateListInstructions = async (input: { * @returns Promise containing the full transaction and the list configuration address */ export const getCreateListTransaction = async (input: { - rpc: Rpc; - payer: TransactionSigner; - authority: TransactionSigner; - }): Promise<{ - transaction: FullTransaction< - TransactionVersion, - TransactionMessageWithFeePayer, - TransactionWithBlockhashLifetime>, - listConfig: Address}> => { - - const {instructions, listConfig} = await getCreateListInstructions(input); - const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); - const transaction = createTransaction({ - feePayer: input.payer, - version: 'legacy', - latestBlockhash, - instructions, - }); - return { - transaction, - listConfig, - }; -} \ No newline at end of file + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; +}): Promise<{ + transaction: FullTransaction< + TransactionVersion, + TransactionMessageWithFeePayer, + TransactionWithBlockhashLifetime + >; + listConfig: Address; +}> => { + const { instructions, listConfig } = await getCreateListInstructions(input); + const { value: latestBlockhash } = await input.rpc + .getLatestBlockhash() + .send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return { + transaction, + listConfig, + }; +}; diff --git a/packages/sdk/src/abl/index.ts b/packages/sdk/src/abl/index.ts index 47f3140..76fe93b 100644 --- a/packages/sdk/src/abl/index.ts +++ b/packages/sdk/src/abl/index.ts @@ -1,3 +1,3 @@ export * from './createList'; export * from './utils'; -export * from './setExtraMetas'; \ No newline at end of file +export * from './setExtraMetas'; diff --git a/packages/sdk/src/abl/setExtraMetas.ts b/packages/sdk/src/abl/setExtraMetas.ts index a7b7223..9c22635 100644 --- a/packages/sdk/src/abl/setExtraMetas.ts +++ b/packages/sdk/src/abl/setExtraMetas.ts @@ -1,17 +1,30 @@ -import { createTransaction, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { ABL_PROGRAM_ID } from "./utils"; +import { + createTransaction, + type Address, + type FullTransaction, + type Instruction, + type Rpc, + type SolanaRpcApi, + type TransactionMessageWithFeePayer, + type TransactionSigner, + type TransactionVersion, + type TransactionWithBlockhashLifetime, +} from 'gill'; +import { ABL_PROGRAM_ID } from './utils'; import { getSetExtraMetasThawInstruction } from '@mosaic/abl'; -import { findMintConfigPda, findThawExtraMetasAccountPda } from '@mosaic/ebalts'; -import { EBALTS_PROGRAM_ID } from "../ebalts"; - +import { + findMintConfigPda, + findThawExtraMetasAccountPda, +} from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from '../ebalts'; /** * Generates instructions for setting extra metadata thaw configuration for a token. - * + * * This function creates instructions to configure the extra accounts metadata * on a specific mint, effectively assigning a specific allow / block list to a token account. * This is used in conjunction with the EBALTS program to permissionlessly thaw token accounts. - * + * * @param input - Configuration parameters for setting extra metadata thaw * @param input.authority - The authority signer who can modify the thaw configuration * @param input.mint - The mint address for which to configure extra metadata thaw @@ -19,34 +32,40 @@ import { EBALTS_PROGRAM_ID } from "../ebalts"; * @returns Promise containing the instructions for setting extra metadata thaw */ export const getSetExtraMetasInstructions = async (input: { - authority: TransactionSigner; - mint: Address; - list: Address; - }): Promise[]> => { - - const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); - const extraMetasThaw = await findThawExtraMetasAccountPda({ mint: input.mint }, { programAddress: ABL_PROGRAM_ID }); - + authority: TransactionSigner; + mint: Address; + list: Address; +}): Promise[]> => { + const mintConfigPda = await findMintConfigPda( + { mint: input.mint }, + { programAddress: EBALTS_PROGRAM_ID } + ); + const extraMetasThaw = await findThawExtraMetasAccountPda( + { mint: input.mint }, + { programAddress: ABL_PROGRAM_ID } + ); - const createListInstruction = getSetExtraMetasThawInstruction({ + const createListInstruction = getSetExtraMetasThawInstruction( + { authority: input.authority, listConfig: input.list, mint: input.mint, ebaltsMintConfig: mintConfigPda[0], extraMetasThaw: extraMetasThaw[0], }, - { programAddress: ABL_PROGRAM_ID }); - - return [createListInstruction]; -} + { programAddress: ABL_PROGRAM_ID } + ); + + return [createListInstruction]; +}; /** * Creates a complete transaction for setting extra metadata thaw configuration for a token. - * + * * This function builds a full transaction that can be signed and sent to configure * the thaw settings for extra metadata on a specific mint. The transaction includes * the necessary instructions and uses the latest blockhash for proper construction. - * + * * @param input - Configuration parameters for the transaction * @param input.rpc - The Solana RPC client instance * @param input.payer - The transaction fee payer signer @@ -56,23 +75,27 @@ export const getSetExtraMetasInstructions = async (input: { * @returns Promise containing the full transaction for setting extra metadata thaw */ export const getSetExtraMetasTransaction = async (input: { - rpc: Rpc; - payer: TransactionSigner; - authority: TransactionSigner; - mint: Address; - list: Address; - }): Promise> => { - - const instructions = await getSetExtraMetasInstructions(input); - const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); - const transaction = createTransaction({ - feePayer: input.payer, - version: 'legacy', - latestBlockhash, - instructions, - }); - return transaction; -} \ No newline at end of file + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; + list: Address; +}): Promise< + FullTransaction< + TransactionVersion, + TransactionMessageWithFeePayer, + TransactionWithBlockhashLifetime + > +> => { + const instructions = await getSetExtraMetasInstructions(input); + const { value: latestBlockhash } = await input.rpc + .getLatestBlockhash() + .send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return transaction; +}; diff --git a/packages/sdk/src/abl/utils.ts b/packages/sdk/src/abl/utils.ts index 2978b4a..09b5937 100644 --- a/packages/sdk/src/abl/utils.ts +++ b/packages/sdk/src/abl/utils.ts @@ -1,9 +1,10 @@ -import type { Address } from "gill"; +import type { Address } from 'gill'; /** * The program ID for the ABL (Allowlist/Blocklist) program. - * + * * This is the address of the ABL program that handles allowlist and blocklist * functionality for token gating and access control. */ -export const ABL_PROGRAM_ID = '8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N' as Address; \ No newline at end of file +export const ABL_PROGRAM_ID = + '8hNxmWetsVptuZ5LGYC6fM4xTpoUfPijz3NyYctyM79N' as Address; diff --git a/packages/sdk/src/ebalts/createConfig.ts b/packages/sdk/src/ebalts/createConfig.ts index 50e3ab2..b7b4baa 100644 --- a/packages/sdk/src/ebalts/createConfig.ts +++ b/packages/sdk/src/ebalts/createConfig.ts @@ -1,15 +1,25 @@ -import { createTransaction, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { findMintConfigPda, getCreateConfigInstruction } from "@mosaic/ebalts"; -import { EBALTS_PROGRAM_ID } from "./utils"; - +import { + createTransaction, + type Address, + type FullTransaction, + type Instruction, + type Rpc, + type SolanaRpcApi, + type TransactionMessageWithFeePayer, + type TransactionSigner, + type TransactionVersion, + type TransactionWithBlockhashLifetime, +} from 'gill'; +import { findMintConfigPda, getCreateConfigInstruction } from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from './utils'; /** * Generates instructions for creating a new EBALTS mint configuration. - * + * * This function creates the necessary instructions to initialize a mint configuration * for the EBALTS program. This configuration enables enhanced balance features like * gating programs and permissionless thaw operations for a specific mint. - * + * * @param input - Configuration parameters for EBALTS mint config creation * @param input.authority - The authority signer who will control the mint configuration * @param input.mint - The mint address for which to create the configuration @@ -17,35 +27,39 @@ import { EBALTS_PROGRAM_ID } from "./utils"; * @returns Promise containing the instructions and the mint configuration address */ export const getCreateConfigInstructions = async (input: { - authority: TransactionSigner; - mint: Address; - gatingProgram: Address; - }): Promise<{instructions: Instruction[], mintConfig: Address}> => { - - const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); + authority: TransactionSigner; + mint: Address; + gatingProgram: Address; +}): Promise<{ instructions: Instruction[]; mintConfig: Address }> => { + const mintConfigPda = await findMintConfigPda( + { mint: input.mint }, + { programAddress: EBALTS_PROGRAM_ID } + ); - const createConfigInstruction = getCreateConfigInstruction({ - payer: input.authority.address, - authority: input.authority, - mint: input.mint, - mintConfig: mintConfigPda[0], - gatingProgram: input.gatingProgram, - }, - { programAddress: EBALTS_PROGRAM_ID }); + const createConfigInstruction = getCreateConfigInstruction( + { + payer: input.authority.address, + authority: input.authority, + mint: input.mint, + mintConfig: mintConfigPda[0], + gatingProgram: input.gatingProgram, + }, + { programAddress: EBALTS_PROGRAM_ID } + ); - return { - instructions: [createConfigInstruction], - mintConfig: mintConfigPda[0], - }; -} + return { + instructions: [createConfigInstruction], + mintConfig: mintConfigPda[0], + }; +}; /** * Creates a complete transaction for initializing a new EBALTS mint configuration. - * + * * This function builds a full transaction that can be signed and sent to create * an EBALTS mint configuration. The transaction includes the necessary instructions * and uses the latest blockhash for proper transaction construction. - * + * * @param input - Configuration parameters for the transaction * @param input.rpc - The Solana RPC client instance * @param input.payer - The transaction fee payer signer @@ -55,28 +69,31 @@ export const getCreateConfigInstructions = async (input: { * @returns Promise containing the full transaction and the mint configuration address */ export const getCreateConfigTransaction = async (input: { - rpc: Rpc; - payer: TransactionSigner; - authority: TransactionSigner; - mint: Address; - gatingProgram: Address; - }): Promise<{ - transaction: FullTransaction< - TransactionVersion, - TransactionMessageWithFeePayer, - TransactionWithBlockhashLifetime>, - mintConfig: Address}> => { - - const {instructions, mintConfig} = await getCreateConfigInstructions(input); - const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); - const transaction = createTransaction({ - feePayer: input.payer, - version: 'legacy', - latestBlockhash, - instructions, - }); - return { - transaction, - mintConfig, - }; -} \ No newline at end of file + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; + gatingProgram: Address; +}): Promise<{ + transaction: FullTransaction< + TransactionVersion, + TransactionMessageWithFeePayer, + TransactionWithBlockhashLifetime + >; + mintConfig: Address; +}> => { + const { instructions, mintConfig } = await getCreateConfigInstructions(input); + const { value: latestBlockhash } = await input.rpc + .getLatestBlockhash() + .send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return { + transaction, + mintConfig, + }; +}; diff --git a/packages/sdk/src/ebalts/enablePermissionlessThaw.ts b/packages/sdk/src/ebalts/enablePermissionlessThaw.ts index d546049..e0db3ce 100644 --- a/packages/sdk/src/ebalts/enablePermissionlessThaw.ts +++ b/packages/sdk/src/ebalts/enablePermissionlessThaw.ts @@ -1,46 +1,64 @@ -import { createTransaction, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { findMintConfigPda, getTogglePermissionlessInstructionsInstruction } from "@mosaic/ebalts"; -import { EBALTS_PROGRAM_ID } from "./utils"; - +import { + createTransaction, + type Address, + type FullTransaction, + type Instruction, + type Rpc, + type SolanaRpcApi, + type TransactionMessageWithFeePayer, + type TransactionSigner, + type TransactionVersion, + type TransactionWithBlockhashLifetime, +} from 'gill'; +import { + findMintConfigPda, + getTogglePermissionlessInstructionsInstruction, +} from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from './utils'; /** * Generates instructions for enabling permissionless thaw operations on a mint. - * + * * This function creates instructions to enable permissionless thaw functionality * for a specific mint. When enabled, any user can thaw frozen token accounts * without requiring the freeze authority's signature, while freeze operations * remain restricted to the authority. - * + * * @param input - Configuration parameters for enabling permissionless thaw * @param input.authority - The authority signer who can modify the thaw configuration * @param input.mint - The mint address for which to enable permissionless thaw * @returns Promise containing the instructions for enabling permissionless thaw */ export const getEnablePermissionlessThawInstructions = async (input: { - authority: TransactionSigner; - mint: Address; - }): Promise[]> => { - - const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); + authority: TransactionSigner; + mint: Address; +}): Promise[]> => { + const mintConfigPda = await findMintConfigPda( + { mint: input.mint }, + { programAddress: EBALTS_PROGRAM_ID } + ); - const enablePermissionlessThawInstruction = getTogglePermissionlessInstructionsInstruction({ + const enablePermissionlessThawInstruction = + getTogglePermissionlessInstructionsInstruction( + { authority: input.authority, mintConfig: mintConfigPda[0], thawEnabled: true, freezeEnabled: false, }, - { programAddress: EBALTS_PROGRAM_ID }); + { programAddress: EBALTS_PROGRAM_ID } + ); - return [enablePermissionlessThawInstruction]; -} + return [enablePermissionlessThawInstruction]; +}; /** * Creates a complete transaction for enabling permissionless thaw operations. - * + * * This function builds a full transaction that can be signed and sent to enable * permissionless thaw functionality for a specific mint. The transaction includes * the necessary instructions and uses the latest blockhash for proper construction. - * + * * @param input - Configuration parameters for the transaction * @param input.rpc - The Solana RPC client instance * @param input.payer - The transaction fee payer signer @@ -49,22 +67,26 @@ export const getEnablePermissionlessThawInstructions = async (input: { * @returns Promise containing the full transaction for enabling permissionless thaw */ export const getEnablePermissionlessThawTransaction = async (input: { - rpc: Rpc; - payer: TransactionSigner; - authority: TransactionSigner; - mint: Address; - }): Promise> => { - - const instructions = await getEnablePermissionlessThawInstructions(input); - const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); - const transaction = createTransaction({ - feePayer: input.payer, - version: 'legacy', - latestBlockhash, - instructions, - }); - return transaction; -} \ No newline at end of file + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; +}): Promise< + FullTransaction< + TransactionVersion, + TransactionMessageWithFeePayer, + TransactionWithBlockhashLifetime + > +> => { + const instructions = await getEnablePermissionlessThawInstructions(input); + const { value: latestBlockhash } = await input.rpc + .getLatestBlockhash() + .send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return transaction; +}; diff --git a/packages/sdk/src/ebalts/index.ts b/packages/sdk/src/ebalts/index.ts index 4797d64..7806d40 100644 --- a/packages/sdk/src/ebalts/index.ts +++ b/packages/sdk/src/ebalts/index.ts @@ -1,7 +1,5 @@ - - export * from './utils'; export * from './createConfig'; export * from './setGatingProgram'; export * from './enablePermissionlessThaw'; -export * from './thawPermissionless'; \ No newline at end of file +export * from './thawPermissionless'; diff --git a/packages/sdk/src/ebalts/setGatingProgram.ts b/packages/sdk/src/ebalts/setGatingProgram.ts index 307d4e3..686a914 100644 --- a/packages/sdk/src/ebalts/setGatingProgram.ts +++ b/packages/sdk/src/ebalts/setGatingProgram.ts @@ -1,15 +1,28 @@ -import { createTransaction, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { findMintConfigPda, getSetGatingProgramInstruction } from "@mosaic/ebalts"; -import { EBALTS_PROGRAM_ID } from "./utils"; - +import { + createTransaction, + type Address, + type FullTransaction, + type Instruction, + type Rpc, + type SolanaRpcApi, + type TransactionMessageWithFeePayer, + type TransactionSigner, + type TransactionVersion, + type TransactionWithBlockhashLifetime, +} from 'gill'; +import { + findMintConfigPda, + getSetGatingProgramInstruction, +} from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from './utils'; /** * Generates instructions for setting or updating the gating program for a mint. - * + * * This function creates instructions to configure which program will gate operations * on a specific mint. The gating program controls access to the permissionless thaw functionality. * If no gating program is provided, it defaults to the System Program (11111111111111111111111111111111). - * + * * @param input - Configuration parameters for setting the gating program * @param input.authority - The authority signer who can modify the gating configuration * @param input.mint - The mint address for which to set the gating program @@ -17,31 +30,36 @@ import { EBALTS_PROGRAM_ID } from "./utils"; * @returns Promise containing the instructions for setting the gating program */ export const getSetGatingProgramInstructions = async (input: { - authority: TransactionSigner; - mint: Address; - gatingProgram: Address; - }): Promise[]> => { - - const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); - const gatingProgram = (input.gatingProgram || '11111111111111111111111111111111') as Address; + authority: TransactionSigner; + mint: Address; + gatingProgram: Address; +}): Promise[]> => { + const mintConfigPda = await findMintConfigPda( + { mint: input.mint }, + { programAddress: EBALTS_PROGRAM_ID } + ); + const gatingProgram = (input.gatingProgram || + '11111111111111111111111111111111') as Address; - const setGatingProgramInstruction = getSetGatingProgramInstruction({ - authority: input.authority, - mintConfig: mintConfigPda[0], - newGatingProgram: gatingProgram, - }, - { programAddress: EBALTS_PROGRAM_ID }); + const setGatingProgramInstruction = getSetGatingProgramInstruction( + { + authority: input.authority, + mintConfig: mintConfigPda[0], + newGatingProgram: gatingProgram, + }, + { programAddress: EBALTS_PROGRAM_ID } + ); - return [setGatingProgramInstruction]; -} + return [setGatingProgramInstruction]; +}; /** * Creates a complete transaction for setting or updating the gating program. - * + * * This function builds a full transaction that can be signed and sent to configure * the gating program for a specific mint. The transaction includes the necessary * instructions and uses the latest blockhash for proper construction. - * + * * @param input - Configuration parameters for the transaction * @param input.rpc - The Solana RPC client instance * @param input.payer - The transaction fee payer signer @@ -51,23 +69,27 @@ export const getSetGatingProgramInstructions = async (input: { * @returns Promise containing the full transaction for setting the gating program */ export const getSetGatingProgramTransaction = async (input: { - rpc: Rpc; - payer: TransactionSigner; - authority: TransactionSigner; - mint: Address; - gatingProgram: Address; - }): Promise> => { - - const instructions = await getSetGatingProgramInstructions(input); - const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); - const transaction = createTransaction({ - feePayer: input.payer, - version: 'legacy', - latestBlockhash, - instructions, - }); - return transaction; -} \ No newline at end of file + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; + gatingProgram: Address; +}): Promise< + FullTransaction< + TransactionVersion, + TransactionMessageWithFeePayer, + TransactionWithBlockhashLifetime + > +> => { + const instructions = await getSetGatingProgramInstructions(input); + const { value: latestBlockhash } = await input.rpc + .getLatestBlockhash() + .send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return transaction; +}; diff --git a/packages/sdk/src/ebalts/thawPermissionless.ts b/packages/sdk/src/ebalts/thawPermissionless.ts index a93d0a9..597d396 100644 --- a/packages/sdk/src/ebalts/thawPermissionless.ts +++ b/packages/sdk/src/ebalts/thawPermissionless.ts @@ -1,17 +1,36 @@ -import { createTransaction, fetchEncodedAccount, lamports, type Address, type FullTransaction, type Instruction, type Rpc, type SolanaRpcApi, type TransactionMessageWithFeePayer, type TransactionSigner, type TransactionVersion, type TransactionWithBlockhashLifetime } from "gill"; -import { createThawPermissionlessInstructionWithExtraMetas, findMintConfigPda } from "@mosaic/ebalts"; -import { EBALTS_PROGRAM_ID } from "./utils"; -import { getTokenEncoder, AccountState, TOKEN_2022_PROGRAM_ADDRESS } from "gill/programs"; - +import { + createTransaction, + fetchEncodedAccount, + lamports, + type Address, + type FullTransaction, + type Instruction, + type Rpc, + type SolanaRpcApi, + type TransactionMessageWithFeePayer, + type TransactionSigner, + type TransactionVersion, + type TransactionWithBlockhashLifetime, +} from 'gill'; +import { + createThawPermissionlessInstructionWithExtraMetas, + findMintConfigPda, +} from '@mosaic/ebalts'; +import { EBALTS_PROGRAM_ID } from './utils'; +import { + getTokenEncoder, + AccountState, + TOKEN_2022_PROGRAM_ADDRESS, +} from 'gill/programs'; /** * Generates instructions for performing a permissionless thaw operation on a token account. - * + * * This function creates instructions to thaw a frozen token account without requiring * the freeze authority's signature. This is only possible if permissionless thaw has * been enabled for the mint. The function includes logic to handle extra accounts resolution * that may be required to perform the thaw. - * + * * @param input - Configuration parameters for the permissionless thaw operation * @param input.rpc - The Solana RPC client instance for fetching account data * @param input.authority - The authority signer performing the thaw operation @@ -21,55 +40,64 @@ import { getTokenEncoder, AccountState, TOKEN_2022_PROGRAM_ADDRESS } from "gill/ * @returns Promise containing the instructions for the permissionless thaw operation */ export const getThawPermissionlessInstructions = async (input: { - rpc: Rpc; - authority: TransactionSigner; - mint: Address; - tokenAccount: Address; - tokenAccountOwner: Address; - }): Promise[]> => { - - const mintConfigPda = await findMintConfigPda({ mint: input.mint }, { programAddress: EBALTS_PROGRAM_ID }); + rpc: Rpc; + authority: TransactionSigner; + mint: Address; + tokenAccount: Address; + tokenAccountOwner: Address; +}): Promise[]> => { + const mintConfigPda = await findMintConfigPda( + { mint: input.mint }, + { programAddress: EBALTS_PROGRAM_ID } + ); - const thawPermissionlessInstruction = await createThawPermissionlessInstructionWithExtraMetas(input.authority, input.tokenAccount, input.mint, mintConfigPda[0], input.tokenAccountOwner, EBALTS_PROGRAM_ID, - async (address: Address) => { - const data = getTokenEncoder().encode({ - amount: 0, - closeAuthority: null, - delegate: null, - delegatedAmount: 0, - extensions: null, - isNative: null, - mint: input.mint, - owner: input.tokenAccountOwner, - state: AccountState.Frozen - }); + const thawPermissionlessInstruction = + await createThawPermissionlessInstructionWithExtraMetas( + input.authority, + input.tokenAccount, + input.mint, + mintConfigPda[0], + input.tokenAccountOwner, + EBALTS_PROGRAM_ID, + async (address: Address) => { + const data = getTokenEncoder().encode({ + amount: 0, + closeAuthority: null, + delegate: null, + delegatedAmount: 0, + extensions: null, + isNative: null, + mint: input.mint, + owner: input.tokenAccountOwner, + state: AccountState.Frozen, + }); - if (address === input.tokenAccount) { - return { - exists: true, - address, - data: new Uint8Array(data), - executable: false, - lamports: lamports(BigInt(2157600)), - programAddress: TOKEN_2022_PROGRAM_ADDRESS, - space: BigInt(data.byteLength), - } - } - return await fetchEncodedAccount(input.rpc, address) + if (address === input.tokenAccount) { + return { + exists: true, + address, + data: new Uint8Array(data), + executable: false, + lamports: lamports(BigInt(2157600)), + programAddress: TOKEN_2022_PROGRAM_ADDRESS, + space: BigInt(data.byteLength), + }; } - ); + return await fetchEncodedAccount(input.rpc, address); + } + ); - return [thawPermissionlessInstruction]; -} + return [thawPermissionlessInstruction]; +}; /** * Creates a complete transaction for performing a permissionless thaw operation. - * + * * This function builds a full transaction that can be signed and sent to thaw * a frozen token account without requiring the freeze authority's signature. * The transaction includes the necessary instructions and uses the latest * blockhash for proper construction. - * + * * @param input - Configuration parameters for the transaction * @param input.rpc - The Solana RPC client instance * @param input.payer - The transaction fee payer signer @@ -80,24 +108,28 @@ export const getThawPermissionlessInstructions = async (input: { * @returns Promise containing the full transaction for the permissionless thaw operation */ export const getThawPermissionlessTransaction = async (input: { - rpc: Rpc; - payer: TransactionSigner; - authority: TransactionSigner; - mint: Address; - tokenAccount: Address; - tokenAccountOwner: Address; - }): Promise> => { - - const instructions = await getThawPermissionlessInstructions(input); - const { value: latestBlockhash } = await input.rpc.getLatestBlockhash().send(); - const transaction = createTransaction({ - feePayer: input.payer, - version: 'legacy', - latestBlockhash, - instructions, - }); - return transaction; -} \ No newline at end of file + rpc: Rpc; + payer: TransactionSigner; + authority: TransactionSigner; + mint: Address; + tokenAccount: Address; + tokenAccountOwner: Address; +}): Promise< + FullTransaction< + TransactionVersion, + TransactionMessageWithFeePayer, + TransactionWithBlockhashLifetime + > +> => { + const instructions = await getThawPermissionlessInstructions(input); + const { value: latestBlockhash } = await input.rpc + .getLatestBlockhash() + .send(); + const transaction = createTransaction({ + feePayer: input.payer, + version: 'legacy', + latestBlockhash, + instructions, + }); + return transaction; +}; diff --git a/packages/sdk/src/ebalts/utils.ts b/packages/sdk/src/ebalts/utils.ts index 8570917..51ff6e2 100644 --- a/packages/sdk/src/ebalts/utils.ts +++ b/packages/sdk/src/ebalts/utils.ts @@ -1,8 +1,9 @@ -import type { Address } from "gill"; +import type { Address } from 'gill'; /** * The program ID for the EBALTS program. - * + * * This is the address of the EBALTS program that provides the ability to permissionlessly thaw token accounts. */ -export const EBALTS_PROGRAM_ID = '81H44JYqk1p8RUks7pNJjhQG4Pj8FcaJeTUxZKN3JfLc' as Address; \ No newline at end of file +export const EBALTS_PROGRAM_ID = + '81H44JYqk1p8RUks7pNJjhQG4Pj8FcaJeTUxZKN3JfLc' as Address; diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 4135c33..57ebda8 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -5,4 +5,4 @@ export * from './management/freeze'; export * from './management/force-transfer'; export * from './transactionUtil'; export * from './abl'; -export * from './ebalts'; \ No newline at end of file +export * from './ebalts'; diff --git a/packages/sdk/src/issuance/createMint.ts b/packages/sdk/src/issuance/createMint.ts index 94a18c0..b537afa 100644 --- a/packages/sdk/src/issuance/createMint.ts +++ b/packages/sdk/src/issuance/createMint.ts @@ -74,9 +74,7 @@ export class Token { withDefaultAccountState(initialState: boolean): Token { const defaultAccountStateExtension = extension('DefaultAccountState', { - state: initialState - ? AccountState.Initialized - : AccountState.Frozen, + state: initialState ? AccountState.Initialized : AccountState.Frozen, }); this.extensions.push(defaultAccountStateExtension); return this; diff --git a/packages/tlv-account-resolution/src/errors.ts b/packages/tlv-account-resolution/src/errors.ts index b404749..0dc1eb5 100644 --- a/packages/tlv-account-resolution/src/errors.ts +++ b/packages/tlv-account-resolution/src/errors.ts @@ -1,96 +1,96 @@ /** Base class for errors */ export abstract class TokenError extends Error { - constructor(message?: string) { - super(message); - } + constructor(message?: string) { + super(message); + } } /** Thrown if an account is not found at the expected address */ export class TokenAccountNotFoundError extends TokenError { - name = 'TokenAccountNotFoundError'; + name = 'TokenAccountNotFoundError'; } /** Thrown if a program state account is not a valid Account */ export class TokenInvalidAccountError extends TokenError { - name = 'TokenInvalidAccountError'; + name = 'TokenInvalidAccountError'; } /** Thrown if a program state account does not contain valid data */ export class TokenInvalidAccountDataError extends TokenError { - name = 'TokenInvalidAccountDataError'; + name = 'TokenInvalidAccountDataError'; } /** Thrown if a program state account is not owned by the expected token program */ export class TokenInvalidAccountOwnerError extends TokenError { - name = 'TokenInvalidAccountOwnerError'; + name = 'TokenInvalidAccountOwnerError'; } /** Thrown if the byte length of an program state account doesn't match the expected size */ export class TokenInvalidAccountSizeError extends TokenError { - name = 'TokenInvalidAccountSizeError'; + name = 'TokenInvalidAccountSizeError'; } /** Thrown if the mint of a token account doesn't match the expected mint */ export class TokenInvalidMintError extends TokenError { - name = 'TokenInvalidMintError'; + name = 'TokenInvalidMintError'; } /** Thrown if the owner of a token account doesn't match the expected owner */ export class TokenInvalidOwnerError extends TokenError { - name = 'TokenInvalidOwnerError'; + name = 'TokenInvalidOwnerError'; } /** Thrown if the owner of a token account is a PDA (Program Derived Address) */ export class TokenOwnerOffCurveError extends TokenError { - name = 'TokenOwnerOffCurveError'; + name = 'TokenOwnerOffCurveError'; } /** Thrown if an instruction's program is invalid */ export class TokenInvalidInstructionProgramError extends TokenError { - name = 'TokenInvalidInstructionProgramError'; + name = 'TokenInvalidInstructionProgramError'; } /** Thrown if an instruction's keys are invalid */ export class TokenInvalidInstructionKeysError extends TokenError { - name = 'TokenInvalidInstructionKeysError'; + name = 'TokenInvalidInstructionKeysError'; } /** Thrown if an instruction's data is invalid */ export class TokenInvalidInstructionDataError extends TokenError { - name = 'TokenInvalidInstructionDataError'; + name = 'TokenInvalidInstructionDataError'; } /** Thrown if an instruction's type is invalid */ export class TokenInvalidInstructionTypeError extends TokenError { - name = 'TokenInvalidInstructionTypeError'; + name = 'TokenInvalidInstructionTypeError'; } /** Thrown if the program does not support the desired instruction */ export class TokenUnsupportedInstructionError extends TokenError { - name = 'TokenUnsupportedInstructionError'; + name = 'TokenUnsupportedInstructionError'; } /** Thrown if the transfer hook extra accounts contains an invalid account index */ export class TokenTransferHookAccountNotFound extends TokenError { - name = 'TokenTransferHookAccountNotFound'; + name = 'TokenTransferHookAccountNotFound'; } /** Thrown if the transfer hook extra accounts contains an invalid seed */ export class TokenTransferHookInvalidSeed extends TokenError { - name = 'TokenTransferHookInvalidSeed'; + name = 'TokenTransferHookInvalidSeed'; } /** Thrown if account data required by an extra account meta seed config could not be fetched */ export class TokenTransferHookAccountDataNotFound extends TokenError { - name = 'TokenTransferHookAccountDataNotFound'; + name = 'TokenTransferHookAccountDataNotFound'; } /** Thrown if pubkey data extra accounts config is invalid */ export class TokenTransferHookInvalidPubkeyData extends TokenError { - name = 'TokenTransferHookInvalidPubkeyData'; + name = 'TokenTransferHookInvalidPubkeyData'; } /** Thrown if pubkey data source is too small for a pubkey */ export class TokenTransferHookPubkeyDataTooSmall extends TokenError { - name = 'TokenTransferHookPubkeyDataTooSmall'; + name = 'TokenTransferHookPubkeyDataTooSmall'; } diff --git a/packages/tlv-account-resolution/src/index.ts b/packages/tlv-account-resolution/src/index.ts index 6837096..2b33f05 100644 --- a/packages/tlv-account-resolution/src/index.ts +++ b/packages/tlv-account-resolution/src/index.ts @@ -1,4 +1,4 @@ export * from './state'; export * from './seeds'; export * from './pubkeyData'; -export * from './errors'; \ No newline at end of file +export * from './errors'; diff --git a/packages/tlv-account-resolution/src/pubkeyData.ts b/packages/tlv-account-resolution/src/pubkeyData.ts index aad94ff..f28df52 100644 --- a/packages/tlv-account-resolution/src/pubkeyData.ts +++ b/packages/tlv-account-resolution/src/pubkeyData.ts @@ -1,63 +1,75 @@ - import { - TokenTransferHookAccountDataNotFound, - TokenTransferHookInvalidPubkeyData, - TokenTransferHookPubkeyDataTooSmall, - TokenTransferHookAccountNotFound, + TokenTransferHookAccountDataNotFound, + TokenTransferHookInvalidPubkeyData, + TokenTransferHookPubkeyDataTooSmall, + TokenTransferHookAccountNotFound, } from './errors.js'; -import { type Address, type AccountMeta, getAddressDecoder, type MaybeEncodedAccount } from '@solana/kit'; - +import { + type Address, + type AccountMeta, + getAddressDecoder, + type MaybeEncodedAccount, +} from '@solana/kit'; export async function unpackPubkeyData( - keyDataConfig: Uint8Array, - previousMetas: AccountMeta[], - instructionData: Buffer, - accountRetriever: (address: Address) => Promise>, + keyDataConfig: Uint8Array, + previousMetas: AccountMeta[], + instructionData: Buffer, + accountRetriever: (address: Address) => Promise> ): Promise
{ - const [discriminator, ...rest] = keyDataConfig; - const remaining = new Uint8Array(rest); - switch (discriminator) { - case 1: - return unpackPubkeyDataFromInstructionData(remaining, instructionData); - case 2: - return unpackPubkeyDataFromAccountData(remaining, previousMetas, accountRetriever); - default: - throw new TokenTransferHookInvalidPubkeyData(); - } + const [discriminator, ...rest] = keyDataConfig; + const remaining = new Uint8Array(rest); + switch (discriminator) { + case 1: + return unpackPubkeyDataFromInstructionData(remaining, instructionData); + case 2: + return unpackPubkeyDataFromAccountData( + remaining, + previousMetas, + accountRetriever + ); + default: + throw new TokenTransferHookInvalidPubkeyData(); + } } -function unpackPubkeyDataFromInstructionData(remaining: Uint8Array, instructionData: Buffer): Address { - if (remaining.length < 1) { - throw new TokenTransferHookInvalidPubkeyData(); - } - const dataIndex = remaining[0]; - if (instructionData.length < dataIndex + 32) { - throw new TokenTransferHookPubkeyDataTooSmall(); - } - return getAddressDecoder().decode(instructionData, dataIndex); - //return new PublicKey(instructionData.subarray(dataIndex, dataIndex + PUBLIC_KEY_LENGTH)); +function unpackPubkeyDataFromInstructionData( + remaining: Uint8Array, + instructionData: Buffer +): Address { + if (remaining.length < 1) { + throw new TokenTransferHookInvalidPubkeyData(); + } + const dataIndex = remaining[0]; + if (instructionData.length < dataIndex + 32) { + throw new TokenTransferHookPubkeyDataTooSmall(); + } + return getAddressDecoder().decode(instructionData, dataIndex); + //return new PublicKey(instructionData.subarray(dataIndex, dataIndex + PUBLIC_KEY_LENGTH)); } async function unpackPubkeyDataFromAccountData( - remaining: Uint8Array, - previousMetas: AccountMeta[], - accountRetriever: (address: Address) => Promise>, + remaining: Uint8Array, + previousMetas: AccountMeta[], + accountRetriever: (address: Address) => Promise> ): Promise
{ - if (remaining.length < 2) { - throw new TokenTransferHookInvalidPubkeyData(); - } - const [accountIndex, dataIndex] = remaining; - if (previousMetas.length <= accountIndex) { - throw new TokenTransferHookAccountDataNotFound(); - } - const accountInfo = await accountRetriever(previousMetas[accountIndex].address); - //const accountInfo = await connection.getAccountInfo(); - if (!accountInfo.exists) { - throw new TokenTransferHookAccountNotFound(); - } - if (accountInfo.data.length < dataIndex + 32) { - throw new TokenTransferHookPubkeyDataTooSmall(); - } - return getAddressDecoder().decode(accountInfo.data, dataIndex); - //return new PublicKey(accountInfo.data.subarray(dataIndex, dataIndex + PUBLIC_KEY_LENGTH)); + if (remaining.length < 2) { + throw new TokenTransferHookInvalidPubkeyData(); + } + const [accountIndex, dataIndex] = remaining; + if (previousMetas.length <= accountIndex) { + throw new TokenTransferHookAccountDataNotFound(); + } + const accountInfo = await accountRetriever( + previousMetas[accountIndex].address + ); + //const accountInfo = await connection.getAccountInfo(); + if (!accountInfo.exists) { + throw new TokenTransferHookAccountNotFound(); + } + if (accountInfo.data.length < dataIndex + 32) { + throw new TokenTransferHookPubkeyDataTooSmall(); + } + return getAddressDecoder().decode(accountInfo.data, dataIndex); + //return new PublicKey(accountInfo.data.subarray(dataIndex, dataIndex + PUBLIC_KEY_LENGTH)); } diff --git a/packages/tlv-account-resolution/src/seeds.ts b/packages/tlv-account-resolution/src/seeds.ts index f435cbd..265cef6 100644 --- a/packages/tlv-account-resolution/src/seeds.ts +++ b/packages/tlv-account-resolution/src/seeds.ts @@ -1,13 +1,17 @@ - import { - TokenTransferHookAccountDataNotFound, - TokenTransferHookInvalidSeed, + TokenTransferHookAccountDataNotFound, + TokenTransferHookInvalidSeed, } from './errors.js'; -import { type Address, type AccountMeta, getAddressEncoder, type MaybeEncodedAccount } from '@solana/kit'; +import { + type Address, + type AccountMeta, + getAddressEncoder, + type MaybeEncodedAccount, +} from '@solana/kit'; interface Seed { - data: Buffer; - packedLength: number; + data: Buffer; + packedLength: number; } const DISCRIMINATOR_SPAN = 1; @@ -20,112 +24,131 @@ const ACCOUNT_DATA_OFFSET_SPAN = 1; const ACCOUNT_DATA_LENGTH_SPAN = 1; function unpackSeedLiteral(seeds: Uint8Array): Seed { - if (seeds.length < 1) { - throw new TokenTransferHookInvalidSeed(); - } - const [length, ...rest] = seeds; - if (rest.length < length) { - throw new TokenTransferHookInvalidSeed(); - } - return { - data: Buffer.from(rest.slice(0, length)), - packedLength: DISCRIMINATOR_SPAN + LITERAL_LENGTH_SPAN + length, - }; + if (seeds.length < 1) { + throw new TokenTransferHookInvalidSeed(); + } + const [length, ...rest] = seeds; + if (rest.length < length) { + throw new TokenTransferHookInvalidSeed(); + } + return { + data: Buffer.from(rest.slice(0, length)), + packedLength: DISCRIMINATOR_SPAN + LITERAL_LENGTH_SPAN + length, + }; } -function unpackSeedInstructionArg(seeds: Uint8Array, instructionData: Buffer): Seed { - if (seeds.length < 2) { - throw new TokenTransferHookInvalidSeed(); - } - const [index, length] = seeds; - if (instructionData.length < length + index) { - throw new TokenTransferHookInvalidSeed(); - } - return { - data: instructionData.subarray(index, index + length), - packedLength: DISCRIMINATOR_SPAN + INSTRUCTION_ARG_OFFSET_SPAN + INSTRUCTION_ARG_LENGTH_SPAN, - }; +function unpackSeedInstructionArg( + seeds: Uint8Array, + instructionData: Buffer +): Seed { + if (seeds.length < 2) { + throw new TokenTransferHookInvalidSeed(); + } + const [index, length] = seeds; + if (instructionData.length < length + index) { + throw new TokenTransferHookInvalidSeed(); + } + return { + data: instructionData.subarray(index, index + length), + packedLength: + DISCRIMINATOR_SPAN + + INSTRUCTION_ARG_OFFSET_SPAN + + INSTRUCTION_ARG_LENGTH_SPAN, + }; } -function unpackSeedAccountKey(seeds: Uint8Array, previousMetas: AccountMeta[]): Seed { - if (seeds.length < 1) { - throw new TokenTransferHookInvalidSeed(); - } - const [index] = seeds; - if (previousMetas.length <= index) { - throw new TokenTransferHookInvalidSeed(); - } - return { - data: Buffer.from(getAddressEncoder().encode(previousMetas[index].address)), - packedLength: DISCRIMINATOR_SPAN + ACCOUNT_KEY_INDEX_SPAN, - }; +function unpackSeedAccountKey( + seeds: Uint8Array, + previousMetas: AccountMeta[] +): Seed { + if (seeds.length < 1) { + throw new TokenTransferHookInvalidSeed(); + } + const [index] = seeds; + if (previousMetas.length <= index) { + throw new TokenTransferHookInvalidSeed(); + } + return { + data: Buffer.from(getAddressEncoder().encode(previousMetas[index].address)), + packedLength: DISCRIMINATOR_SPAN + ACCOUNT_KEY_INDEX_SPAN, + }; } async function unpackSeedAccountData( - seeds: Uint8Array, - previousMetas: AccountMeta[], - accountRetriever: (address: Address) => Promise>, + seeds: Uint8Array, + previousMetas: AccountMeta[], + accountRetriever: (address: Address) => Promise> ): Promise { - if (seeds.length < 3) { - throw new TokenTransferHookInvalidSeed(); - } - const [accountIndex, dataIndex, length] = seeds; - if (previousMetas.length <= accountIndex) { - throw new TokenTransferHookInvalidSeed(); - } - const accountInfo = await accountRetriever(previousMetas[accountIndex].address); - if (!accountInfo.exists) { - throw new TokenTransferHookAccountDataNotFound(); - } - if (accountInfo.data.length < dataIndex + length) { - throw new TokenTransferHookInvalidSeed(); - } - return { - data: Buffer.from(accountInfo.data.subarray(dataIndex, dataIndex + length)), - packedLength: - DISCRIMINATOR_SPAN + ACCOUNT_DATA_ACCOUNT_INDEX_SPAN + ACCOUNT_DATA_OFFSET_SPAN + ACCOUNT_DATA_LENGTH_SPAN, - }; + if (seeds.length < 3) { + throw new TokenTransferHookInvalidSeed(); + } + const [accountIndex, dataIndex, length] = seeds; + if (previousMetas.length <= accountIndex) { + throw new TokenTransferHookInvalidSeed(); + } + const accountInfo = await accountRetriever( + previousMetas[accountIndex].address + ); + if (!accountInfo.exists) { + throw new TokenTransferHookAccountDataNotFound(); + } + if (accountInfo.data.length < dataIndex + length) { + throw new TokenTransferHookInvalidSeed(); + } + return { + data: Buffer.from(accountInfo.data.subarray(dataIndex, dataIndex + length)), + packedLength: + DISCRIMINATOR_SPAN + + ACCOUNT_DATA_ACCOUNT_INDEX_SPAN + + ACCOUNT_DATA_OFFSET_SPAN + + ACCOUNT_DATA_LENGTH_SPAN, + }; } async function unpackFirstSeed( - seeds: Uint8Array, - previousMetas: AccountMeta[], - instructionData: Buffer, - accountRetriever: (address: Address) => Promise>, + seeds: Uint8Array, + previousMetas: AccountMeta[], + instructionData: Buffer, + accountRetriever: (address: Address) => Promise> ): Promise { - const [discriminator, ...rest] = seeds; - const remaining = new Uint8Array(rest); - switch (discriminator) { - case 0: - return null; - case 1: - return unpackSeedLiteral(remaining); - case 2: - return unpackSeedInstructionArg(remaining, instructionData); - case 3: - return unpackSeedAccountKey(remaining, previousMetas); - case 4: - return unpackSeedAccountData(remaining, previousMetas, accountRetriever); - default: - throw new TokenTransferHookInvalidSeed(); - } + const [discriminator, ...rest] = seeds; + const remaining = new Uint8Array(rest); + switch (discriminator) { + case 0: + return null; + case 1: + return unpackSeedLiteral(remaining); + case 2: + return unpackSeedInstructionArg(remaining, instructionData); + case 3: + return unpackSeedAccountKey(remaining, previousMetas); + case 4: + return unpackSeedAccountData(remaining, previousMetas, accountRetriever); + default: + throw new TokenTransferHookInvalidSeed(); + } } export async function unpackSeeds( - seeds: Uint8Array, - previousMetas: AccountMeta[], - instructionData: Buffer, - accountRetriever: (address: Address) => Promise>, + seeds: Uint8Array, + previousMetas: AccountMeta[], + instructionData: Buffer, + accountRetriever: (address: Address) => Promise> ): Promise { - const unpackedSeeds: Buffer[] = []; - let i = 0; - while (i < 32) { - const seed = await unpackFirstSeed(seeds.slice(i), previousMetas, instructionData, accountRetriever); - if (seed == null) { - break; - } - unpackedSeeds.push(seed.data); - i += seed.packedLength; + const unpackedSeeds: Buffer[] = []; + let i = 0; + while (i < 32) { + const seed = await unpackFirstSeed( + seeds.slice(i), + previousMetas, + instructionData, + accountRetriever + ); + if (seed == null) { + break; } - return unpackedSeeds; + unpackedSeeds.push(seed.data); + i += seed.packedLength; + } + return unpackedSeeds; } diff --git a/packages/tlv-account-resolution/src/state.ts b/packages/tlv-account-resolution/src/state.ts index 2986e18..5efc213 100644 --- a/packages/tlv-account-resolution/src/state.ts +++ b/packages/tlv-account-resolution/src/state.ts @@ -1,139 +1,167 @@ - -import { TokenTransferHookAccountNotFound, TokenTransferHookInvalidPubkeyData } from './errors.js'; +import { + TokenTransferHookAccountNotFound, + TokenTransferHookInvalidPubkeyData, +} from './errors.js'; import { unpackSeeds } from './seeds.js'; import { unpackPubkeyData } from './pubkeyData.js'; -import { type Address, type AccountMeta, getProgramDerivedAddress, AccountRole, mergeRoles, getAddressDecoder, type MaybeEncodedAccount } from '@solana/kit'; - +import { + type Address, + type AccountMeta, + getProgramDerivedAddress, + AccountRole, + mergeRoles, + getAddressDecoder, + type MaybeEncodedAccount, +} from '@solana/kit'; export async function resolveExtraMetas( - accountRetriever: (address: Address) => Promise>, - extraMetasAddress: Address, - previousMetas: AccountMeta[], - instructionData: Buffer, - programId: Address, + accountRetriever: (address: Address) => Promise>, + extraMetasAddress: Address, + previousMetas: AccountMeta[], + instructionData: Buffer, + programId: Address ): Promise { - const account = await accountRetriever(extraMetasAddress); - const extraAccountMetas = getExtraAccountMetas(account); - const resolvedMetas = [...previousMetas]; - for (const extraAccountMeta of extraAccountMetas) { - const resolvedMeta = await resolveExtraAccountMeta(accountRetriever, extraAccountMeta, resolvedMetas, instructionData, programId); - resolvedMetas.push(resolvedMeta); - } - return resolvedMetas; + const account = await accountRetriever(extraMetasAddress); + const extraAccountMetas = getExtraAccountMetas(account); + const resolvedMetas = [...previousMetas]; + for (const extraAccountMeta of extraAccountMetas) { + const resolvedMeta = await resolveExtraAccountMeta( + accountRetriever, + extraAccountMeta, + resolvedMetas, + instructionData, + programId + ); + resolvedMetas.push(resolvedMeta); + } + return resolvedMetas; } /** ExtraAccountMeta as stored by the transfer hook program */ export interface ExtraAccountMeta { - discriminator: number; - addressConfig: Uint8Array; - isSigner: boolean; - isWritable: boolean; + discriminator: number; + addressConfig: Uint8Array; + isSigner: boolean; + isWritable: boolean; } export interface ExtraAccountMetaList { - count: number; - extraAccounts: ExtraAccountMeta[]; + count: number; + extraAccounts: ExtraAccountMeta[]; } - /** Buffer layout for de/serializing a list of ExtraAccountMetaAccountData prefixed by a u32 length */ export interface ExtraAccountMetaAccountData { - instructionDiscriminator: bigint; - length: number; - extraAccountsList: ExtraAccountMetaList; + instructionDiscriminator: bigint; + length: number; + extraAccountsList: ExtraAccountMetaList; } - /** Unpack an extra account metas account and parse the data into a list of ExtraAccountMetas */ -export function getExtraAccountMetas(account: MaybeEncodedAccount): ExtraAccountMeta[] { - if (!account.exists) { - throw new TokenTransferHookAccountNotFound(); - } - return unpackExtraAccountMetas(account.data); -} - -export function unpackExtraAccountMetas( - data: Uint8Array, +export function getExtraAccountMetas( + account: MaybeEncodedAccount ): ExtraAccountMeta[] { - if (data.length < 12) { - throw new TokenTransferHookInvalidPubkeyData(); - } - //const discriminator = data.slice(0,8); - const length = new DataView(data.buffer, 8, 4).getUint32(0, true); - const count = new DataView(data.buffer, 12, 4).getUint32(0, true); - const offset = 16; - - if (length !== count * 35 + 4) { - throw new TokenTransferHookInvalidPubkeyData(); - } - - if (count * 35 > data.length - offset) { - throw new TokenTransferHookInvalidPubkeyData(); - } - - const extraAccounts = []; - for (let i = 0; i < count; i++) { - const extraAccount = data.slice(offset + i * 35, offset + (i + 1) * 35); - extraAccounts.push(unpackExtraAccountMeta(extraAccount)); - } + if (!account.exists) { + throw new TokenTransferHookAccountNotFound(); + } + return unpackExtraAccountMetas(account.data); +} - return extraAccounts; +export function unpackExtraAccountMetas(data: Uint8Array): ExtraAccountMeta[] { + if (data.length < 12) { + throw new TokenTransferHookInvalidPubkeyData(); + } + //const discriminator = data.slice(0,8); + const length = new DataView(data.buffer, 8, 4).getUint32(0, true); + const count = new DataView(data.buffer, 12, 4).getUint32(0, true); + const offset = 16; + + if (length !== count * 35 + 4) { + throw new TokenTransferHookInvalidPubkeyData(); + } + + if (count * 35 > data.length - offset) { + throw new TokenTransferHookInvalidPubkeyData(); + } + + const extraAccounts = []; + for (let i = 0; i < count; i++) { + const extraAccount = data.slice(offset + i * 35, offset + (i + 1) * 35); + extraAccounts.push(unpackExtraAccountMeta(extraAccount)); + } + + return extraAccounts; } export function unpackExtraAccountMeta(data: Uint8Array): ExtraAccountMeta { - const discriminator = data[0]; - const addressConfig = data.slice(1,33); - const isSigner = data[33] === 1; - const isWritable = data[34] === 1; - return { discriminator, addressConfig, isSigner, isWritable }; + const discriminator = data[0]; + const addressConfig = data.slice(1, 33); + const isSigner = data[33] === 1; + const isWritable = data[34] === 1; + return { discriminator, addressConfig, isSigner, isWritable }; } /** Take an ExtraAccountMeta and construct that into an actual AccountMeta */ export async function resolveExtraAccountMeta( - accountRetriever: (address: Address) => Promise>, - extraMeta: ExtraAccountMeta, - previousMetas: AccountMeta[], - instructionData: Buffer, - programId: Address, + accountRetriever: (address: Address) => Promise>, + extraMeta: ExtraAccountMeta, + previousMetas: AccountMeta[], + instructionData: Buffer, + programId: Address ): Promise { - if (extraMeta.discriminator === 0) { - return { - address: getAddressDecoder().decode(extraMeta.addressConfig), - role: flagsToRole(extraMeta.isSigner, extraMeta.isWritable), - }; - } else if (extraMeta.discriminator === 2) { - const pubkey = await unpackPubkeyData(extraMeta.addressConfig, previousMetas, instructionData, accountRetriever); - return { - address: pubkey, - role: flagsToRole(extraMeta.isSigner, extraMeta.isWritable), - }; + if (extraMeta.discriminator === 0) { + return { + address: getAddressDecoder().decode(extraMeta.addressConfig), + role: flagsToRole(extraMeta.isSigner, extraMeta.isWritable), + }; + } else if (extraMeta.discriminator === 2) { + const pubkey = await unpackPubkeyData( + extraMeta.addressConfig, + previousMetas, + instructionData, + accountRetriever + ); + return { + address: pubkey, + role: flagsToRole(extraMeta.isSigner, extraMeta.isWritable), + }; + } + + let seedProgramId: Address = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + + if (extraMeta.discriminator === 1) { + seedProgramId = programId; + } else { + const accountIndex = extraMeta.discriminator - (1 << 7); + if (previousMetas.length <= accountIndex) { + throw new TokenTransferHookAccountNotFound(); } - - let seedProgramId: Address = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; - - if (extraMeta.discriminator === 1) { - seedProgramId = programId; - } else { - const accountIndex = extraMeta.discriminator - (1 << 7); - if (previousMetas.length <= accountIndex) { - throw new TokenTransferHookAccountNotFound(); - } - seedProgramId = previousMetas[accountIndex].address; - } - - const seeds = await unpackSeeds(extraMeta.addressConfig, previousMetas, instructionData, accountRetriever); - - const address = await getProgramDerivedAddress({ - programAddress: seedProgramId, - seeds, - }); - - return { address: address[0], role: flagsToRole(extraMeta.isSigner, extraMeta.isWritable) }; + seedProgramId = previousMetas[accountIndex].address; + } + + const seeds = await unpackSeeds( + extraMeta.addressConfig, + previousMetas, + instructionData, + accountRetriever + ); + + const address = await getProgramDerivedAddress({ + programAddress: seedProgramId, + seeds, + }); + + return { + address: address[0], + role: flagsToRole(extraMeta.isSigner, extraMeta.isWritable), + }; } - function flagsToRole(isSigner: boolean, isWritable: boolean): AccountRole { - const signerRole = isSigner ? AccountRole.READONLY_SIGNER : AccountRole.READONLY; - const writableRole = isWritable ? AccountRole.WRITABLE : AccountRole.READONLY; - return mergeRoles(signerRole, writableRole); -} \ No newline at end of file + const signerRole = isSigner + ? AccountRole.READONLY_SIGNER + : AccountRole.READONLY; + const writableRole = isWritable ? AccountRole.WRITABLE : AccountRole.READONLY; + return mergeRoles(signerRole, writableRole); +} diff --git a/tsconfig.json b/tsconfig.json index 7a0679b..36a059a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,7 +24,9 @@ "paths": { "@mosaic/core": ["./packages/core/src"], "@mosaic/sdk": ["./packages/sdk/src"], - "@mosaic/tlv-account-resolution": ["./packages/tlv-account-resolution/src"], + "@mosaic/tlv-account-resolution": [ + "./packages/tlv-account-resolution/src" + ], "@mosaic/ebalts": ["./packages/ebalts/src"], "@mosaic/cli": ["./packages/cli/src"], "@mosaic/ui": ["./packages/ui/src"], From a64967d1ffbce7ebed3923fc26fd1ba0153269ee Mon Sep 17 00:00:00 2001 From: tiago Date: Thu, 31 Jul 2025 18:23:08 +0100 Subject: [PATCH 6/9] fixed type checks --- packages/ebalts/src/generated/accounts/mintConfig.ts | 2 +- packages/ui/tsconfig.json | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/ebalts/src/generated/accounts/mintConfig.ts b/packages/ebalts/src/generated/accounts/mintConfig.ts index 8377779..5c477a6 100644 --- a/packages/ebalts/src/generated/accounts/mintConfig.ts +++ b/packages/ebalts/src/generated/accounts/mintConfig.ts @@ -33,7 +33,7 @@ import { type MaybeAccount, type MaybeEncodedAccount, } from '@solana/kit'; -import { MintConfigSeeds, findMintConfigPda } from '../pdas'; +import { type MintConfigSeeds, findMintConfigPda } from '../pdas'; export const MINT_CONFIG_DISCRIMINATOR = 1; diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index abb59dc..261072e 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { - "target": "es5", - "lib": ["dom", "dom.iterable", "es6"], + "target": "ES2022", + "lib": ["dom", "dom.iterable", "ES2022"], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -20,7 +20,11 @@ ], "baseUrl": ".", "paths": { - "@/*": ["./src/*"] + "@/*": ["./src/*"], + "@mosaic/sdk": ["../sdk/src"], + "@mosaic/abl": ["../abl/src"], + "@mosaic/ebalts": ["../ebalts/src"], + "@mosaic/tlv-account-resolution": ["../tlv-account-resolution/src"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], From d6f8478727230f5ad50ada94340bdb4ff325b439 Mon Sep 17 00:00:00 2001 From: tiago Date: Thu, 31 Jul 2025 18:53:45 +0100 Subject: [PATCH 7/9] removed .js file extensions from imports --- packages/tlv-account-resolution/src/pubkeyData.ts | 2 +- packages/tlv-account-resolution/src/seeds.ts | 2 +- packages/tlv-account-resolution/src/state.ts | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/tlv-account-resolution/src/pubkeyData.ts b/packages/tlv-account-resolution/src/pubkeyData.ts index f28df52..6db886e 100644 --- a/packages/tlv-account-resolution/src/pubkeyData.ts +++ b/packages/tlv-account-resolution/src/pubkeyData.ts @@ -3,7 +3,7 @@ import { TokenTransferHookInvalidPubkeyData, TokenTransferHookPubkeyDataTooSmall, TokenTransferHookAccountNotFound, -} from './errors.js'; +} from './errors'; import { type Address, type AccountMeta, diff --git a/packages/tlv-account-resolution/src/seeds.ts b/packages/tlv-account-resolution/src/seeds.ts index 265cef6..60e21d0 100644 --- a/packages/tlv-account-resolution/src/seeds.ts +++ b/packages/tlv-account-resolution/src/seeds.ts @@ -1,7 +1,7 @@ import { TokenTransferHookAccountDataNotFound, TokenTransferHookInvalidSeed, -} from './errors.js'; +} from './errors'; import { type Address, type AccountMeta, diff --git a/packages/tlv-account-resolution/src/state.ts b/packages/tlv-account-resolution/src/state.ts index 5efc213..eb2fd77 100644 --- a/packages/tlv-account-resolution/src/state.ts +++ b/packages/tlv-account-resolution/src/state.ts @@ -1,9 +1,9 @@ import { TokenTransferHookAccountNotFound, TokenTransferHookInvalidPubkeyData, -} from './errors.js'; -import { unpackSeeds } from './seeds.js'; -import { unpackPubkeyData } from './pubkeyData.js'; +} from './errors'; +import { unpackSeeds } from './seeds'; +import { unpackPubkeyData } from './pubkeyData'; import { type Address, type AccountMeta, From 8e14060759a4b45dde8260cd059d484370f2c7c7 Mon Sep 17 00:00:00 2001 From: tiago Date: Thu, 31 Jul 2025 19:10:02 +0100 Subject: [PATCH 8/9] Fixed test errors for packages without tests --- package.json | 2 +- packages/abl/jest.config.js | 29 ------------------- packages/ebalts/jest.config.js | 29 ------------------- .../tlv-account-resolution/jest.config.js | 29 ------------------- 4 files changed, 1 insertion(+), 88 deletions(-) delete mode 100644 packages/abl/jest.config.js delete mode 100644 packages/ebalts/jest.config.js delete mode 100644 packages/tlv-account-resolution/jest.config.js diff --git a/package.json b/package.json index fba24ad..389e7e9 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "scripts": { "build": "pnpm --recursive run build", "dev": "pnpm --recursive run dev", - "test": "pnpm --recursive run test", + "test": "pnpm --recursive run test --passWithNoTests", "lint": "pnpm --recursive run lint", "lint:fix": "pnpm --recursive run lint:fix", "format": "prettier --write .", diff --git a/packages/abl/jest.config.js b/packages/abl/jest.config.js deleted file mode 100644 index 38e2b68..0000000 --- a/packages/abl/jest.config.js +++ /dev/null @@ -1,29 +0,0 @@ -/** @type {import('jest').Config} */ -export default { - preset: 'ts-jest/presets/default-esm', - extensionsToTreatAsEsm: ['.ts'], - testEnvironment: 'node', - roots: ['/src'], - testMatch: ['**/__tests__/**/*.test.ts', '**/?(*.)+(spec|test).ts'], - transform: { - '^.+\\.ts$': [ - 'ts-jest', - { - useESM: true, - }, - ], - }, - collectCoverageFrom: [ - 'src/**/*.ts', - '!src/**/*.d.ts', - '!src/**/__tests__/**/*.test.ts', - '!src/**/*.test.ts', - '!src/**/__tests__/setup.ts', - '!src/**/__tests__/test-utils.ts', - ], - moduleNameMapper: { - '^@/(.*)$': '/src/$1', - }, - moduleFileExtensions: ['ts', 'js', 'json'], - setupFilesAfterEnv: ['/src/__tests__/setup.ts'], -}; diff --git a/packages/ebalts/jest.config.js b/packages/ebalts/jest.config.js deleted file mode 100644 index 38e2b68..0000000 --- a/packages/ebalts/jest.config.js +++ /dev/null @@ -1,29 +0,0 @@ -/** @type {import('jest').Config} */ -export default { - preset: 'ts-jest/presets/default-esm', - extensionsToTreatAsEsm: ['.ts'], - testEnvironment: 'node', - roots: ['/src'], - testMatch: ['**/__tests__/**/*.test.ts', '**/?(*.)+(spec|test).ts'], - transform: { - '^.+\\.ts$': [ - 'ts-jest', - { - useESM: true, - }, - ], - }, - collectCoverageFrom: [ - 'src/**/*.ts', - '!src/**/*.d.ts', - '!src/**/__tests__/**/*.test.ts', - '!src/**/*.test.ts', - '!src/**/__tests__/setup.ts', - '!src/**/__tests__/test-utils.ts', - ], - moduleNameMapper: { - '^@/(.*)$': '/src/$1', - }, - moduleFileExtensions: ['ts', 'js', 'json'], - setupFilesAfterEnv: ['/src/__tests__/setup.ts'], -}; diff --git a/packages/tlv-account-resolution/jest.config.js b/packages/tlv-account-resolution/jest.config.js deleted file mode 100644 index 38e2b68..0000000 --- a/packages/tlv-account-resolution/jest.config.js +++ /dev/null @@ -1,29 +0,0 @@ -/** @type {import('jest').Config} */ -export default { - preset: 'ts-jest/presets/default-esm', - extensionsToTreatAsEsm: ['.ts'], - testEnvironment: 'node', - roots: ['/src'], - testMatch: ['**/__tests__/**/*.test.ts', '**/?(*.)+(spec|test).ts'], - transform: { - '^.+\\.ts$': [ - 'ts-jest', - { - useESM: true, - }, - ], - }, - collectCoverageFrom: [ - 'src/**/*.ts', - '!src/**/*.d.ts', - '!src/**/__tests__/**/*.test.ts', - '!src/**/*.test.ts', - '!src/**/__tests__/setup.ts', - '!src/**/__tests__/test-utils.ts', - ], - moduleNameMapper: { - '^@/(.*)$': '/src/$1', - }, - moduleFileExtensions: ['ts', 'js', 'json'], - setupFilesAfterEnv: ['/src/__tests__/setup.ts'], -}; From 56d778b44f22b6158574e507b77f460a3ee5a153 Mon Sep 17 00:00:00 2001 From: tiago Date: Thu, 31 Jul 2025 19:14:19 +0100 Subject: [PATCH 9/9] fixed default account state test --- packages/sdk/src/issuance/__tests__/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/src/issuance/__tests__/index.test.ts b/packages/sdk/src/issuance/__tests__/index.test.ts index cab41a3..80cdf66 100644 --- a/packages/sdk/src/issuance/__tests__/index.test.ts +++ b/packages/sdk/src/issuance/__tests__/index.test.ts @@ -105,7 +105,7 @@ describe('Token', () => { const extension: any = token.getExtensions()[0]; expect(extension.__kind).toBe('DefaultAccountState'); - expect(extension.state).toBe(AccountState.Uninitialized); + expect(extension.state).toBe(AccountState.Frozen); }); });