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/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/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..a2c5b6b --- /dev/null +++ b/packages/abl/codama.json @@ -0,0 +1,10 @@ +{ + "idl": "idl/abl_srfc37.json", + "before": [], + "scripts": { + "js": { + "from": "@codama/renderers-js", + "args": ["src/generated/"] + } + } +} diff --git a/packages/abl/idl/abl_srfc37.json b/packages/abl/idl/abl_srfc37.json new file mode 100644 index 0000000..a221e94 --- /dev/null +++ b/packages/abl/idl/abl_srfc37.json @@ -0,0 +1,370 @@ +{ + "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" + } + ] + } + } + ] +} 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..7c3241f --- /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..aa9a98a --- /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..53deb9b --- /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..f1fa922 --- /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..abf7e0d --- /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..acd0b11 --- /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..b7c474c --- /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..feca781 --- /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..aca962d --- /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..a149f3f --- /dev/null +++ b/packages/abl/src/index.ts @@ -0,0 +1,52 @@ +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'; diff --git a/packages/abl/tsconfig.json b/packages/abl/tsconfig.json new file mode 100644 index 0000000..f7d4c81 --- /dev/null +++ b/packages/abl/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "verbatimModuleSyntax": false + }, + "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..4dcea78 --- /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); diff --git a/packages/cli/src/commands/abl/createList.ts b/packages/cli/src/commands/abl/createList.ts new file mode 100644 index 0000000..3cc8025 --- /dev/null +++ b/packages/cli/src/commands/abl/createList.ts @@ -0,0 +1,63 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +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'; + +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 { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); + const kp = await loadKeypair(options.keypair); + + 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('ABL list 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 ABL list'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); diff --git a/packages/cli/src/commands/abl/setExtraMetas.ts b/packages/cli/src/commands/abl/setExtraMetas.ts new file mode 100644 index 0000000..69390b1 --- /dev/null +++ b/packages/cli/src/commands/abl/setExtraMetas.ts @@ -0,0 +1,67 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +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'; + +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); + + 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!')); + console.log(chalk.cyan('📋 Details:')); + console.log(` ${chalk.bold('Transaction:')} ${signature}`); + } catch (error) { + spinner.fail('Failed to set extra metas'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); diff --git a/packages/cli/src/commands/abl/utils.ts b/packages/cli/src/commands/abl/utils.ts new file mode 100644 index 0000000..e4723b8 --- /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; diff --git a/packages/cli/src/commands/create/arcade-token.ts b/packages/cli/src/commands/create/arcade-token.ts index 3c06ac8..66f7764 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,10 @@ 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..7242c2d --- /dev/null +++ b/packages/cli/src/commands/ebalts/createConfig.ts @@ -0,0 +1,74 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +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'; + +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') + .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 { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); + const kp = await loadKeypair(options.keypair); + + 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' + ); + + process.exit(1); + } + }); diff --git a/packages/cli/src/commands/ebalts/ebalts.ts b/packages/cli/src/commands/ebalts/ebalts.ts new file mode 100644 index 0000000..2009519 --- /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); diff --git a/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts new file mode 100644 index 0000000..5d512bb --- /dev/null +++ b/packages/cli/src/commands/ebalts/enablePermissionlessThaw.ts @@ -0,0 +1,68 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +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'; + +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 { rpc, sendAndConfirmTransaction } = createSolanaClient(rpcUrl); + const kp = await loadKeypair(options.keypair); + + 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 enable permissionless thaw'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + process.exit(1); + } + }); diff --git a/packages/cli/src/commands/ebalts/setGatingProgram.ts b/packages/cli/src/commands/ebalts/setGatingProgram.ts new file mode 100644 index 0000000..92b2f22 --- /dev/null +++ b/packages/cli/src/commands/ebalts/setGatingProgram.ts @@ -0,0 +1,83 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +import ora from 'ora'; +import { getSetGatingProgramTransaction } from '@mosaic/sdk'; +import { createSolanaClient } from '../../utils/rpc.js'; +import { loadKeypair } from '../../utils/solana.js'; +import { signTransactionMessageWithSigners, type Address } from 'gill'; +import { findMintConfigPda } 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 { 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 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('Gating program set successfully!'); + + // Display results + 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('Mint Config:')} ${mintConfigPda[0]}`); + console.log(` ${chalk.bold('Transaction:')} ${signature}`); + } catch (error) { + spinner.fail('Failed to set gating program'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); diff --git a/packages/cli/src/commands/ebalts/thawPermissionless.ts b/packages/cli/src/commands/ebalts/thawPermissionless.ts new file mode 100644 index 0000000..e9cb848 --- /dev/null +++ b/packages/cli/src/commands/ebalts/thawPermissionless.ts @@ -0,0 +1,84 @@ +import { Command } from 'commander'; +import chalk from 'chalk'; +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 { + getAssociatedTokenAccountAddress, + TOKEN_2022_PROGRAM_ADDRESS, +} from 'gill/programs/token'; + +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 { 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 thaw permissionless'); + console.error( + chalk.red('❌ Error:'), + error instanceof Error ? error.message : 'Unknown error' + ); + + process.exit(1); + } + }); diff --git a/packages/cli/src/commands/ebalts/util.ts b/packages/cli/src/commands/ebalts/util.ts new file mode 100644 index 0000000..d451cff --- /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; diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 188ca49..2c27aed 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,6 +33,8 @@ program.addCommand(freezeCommand); program.addCommand(thawCommand); program.addCommand(forceTransferCommand); program.addCommand(inspectMintCommand); +program.addCommand(ebaltsCommand); +program.addCommand(ablCommand); // Global options program diff --git a/packages/ebalts/README.md b/packages/ebalts/README.md new file mode 100644 index 0000000..e69de29 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..5c477a6 --- /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 { type 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..83ef7a7 --- /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..1326164 --- /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..f2aacae --- /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..e6f3c40 --- /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..85193ce --- /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..0eb6040 --- /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..9e9ad13 --- /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..d413b65 --- /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..829e50a --- /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..375fd69 --- /dev/null +++ b/packages/ebalts/src/index.ts @@ -0,0 +1,140 @@ +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'; + +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; +} diff --git a/packages/ebalts/tsconfig.json b/packages/ebalts/tsconfig.json new file mode 100644 index 0000000..f7d4c81 --- /dev/null +++ b/packages/ebalts/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "verbatimModuleSyntax": false + }, + "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..4a90d7c --- /dev/null +++ b/packages/sdk/src/abl/createList.ts @@ -0,0 +1,97 @@ +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(); + + 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], + }; +}; + +/** + * 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; + 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 new file mode 100644 index 0000000..76fe93b --- /dev/null +++ b/packages/sdk/src/abl/index.ts @@ -0,0 +1,3 @@ +export * from './createList'; +export * from './utils'; +export * from './setExtraMetas'; diff --git a/packages/sdk/src/abl/setExtraMetas.ts b/packages/sdk/src/abl/setExtraMetas.ts new file mode 100644 index 0000000..9c22635 --- /dev/null +++ b/packages/sdk/src/abl/setExtraMetas.ts @@ -0,0 +1,101 @@ +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'; + +/** + * 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; + 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]; +}; + +/** + * 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; + 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 new file mode 100644 index 0000000..09b5937 --- /dev/null +++ b/packages/sdk/src/abl/utils.ts @@ -0,0 +1,10 @@ +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; diff --git a/packages/sdk/src/ebalts/createConfig.ts b/packages/sdk/src/ebalts/createConfig.ts new file mode 100644 index 0000000..b7b4baa --- /dev/null +++ b/packages/sdk/src/ebalts/createConfig.ts @@ -0,0 +1,99 @@ +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 + * @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; + 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], + }; +}; + +/** + * 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; + 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 new file mode 100644 index 0000000..e0db3ce --- /dev/null +++ b/packages/sdk/src/ebalts/enablePermissionlessThaw.ts @@ -0,0 +1,92 @@ +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 } + ); + + const enablePermissionlessThawInstruction = + getTogglePermissionlessInstructionsInstruction( + { + authority: input.authority, + mintConfig: mintConfigPda[0], + thawEnabled: true, + freezeEnabled: false, + }, + { programAddress: EBALTS_PROGRAM_ID } + ); + + 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; + 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 new file mode 100644 index 0000000..7806d40 --- /dev/null +++ b/packages/sdk/src/ebalts/index.ts @@ -0,0 +1,5 @@ +export * from './utils'; +export * from './createConfig'; +export * from './setGatingProgram'; +export * from './enablePermissionlessThaw'; +export * from './thawPermissionless'; diff --git a/packages/sdk/src/ebalts/setGatingProgram.ts b/packages/sdk/src/ebalts/setGatingProgram.ts new file mode 100644 index 0000000..686a914 --- /dev/null +++ b/packages/sdk/src/ebalts/setGatingProgram.ts @@ -0,0 +1,95 @@ +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 + * @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; + 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]; +}; + +/** + * 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; + 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 new file mode 100644 index 0000000..597d396 --- /dev/null +++ b/packages/sdk/src/ebalts/thawPermissionless.ts @@ -0,0 +1,135 @@ +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 + * @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; + 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, + }); + + 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]; +}; + +/** + * 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; + 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 new file mode 100644 index 0000000..51ff6e2 --- /dev/null +++ b/packages/sdk/src/ebalts/utils.ts @@ -0,0 +1,9 @@ +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; diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index a5e5a60..57ebda8 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'; 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); }); }); diff --git a/packages/sdk/src/issuance/createMint.ts b/packages/sdk/src/issuance/createMint.ts index e452ea9..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.Uninitialized, + state: initialState ? AccountState.Initialized : 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/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/README.md b/packages/tlv-account-resolution/README.md new file mode 100644 index 0000000..e69de29 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..0dc1eb5 --- /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..2b33f05 --- /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'; diff --git a/packages/tlv-account-resolution/src/pubkeyData.ts b/packages/tlv-account-resolution/src/pubkeyData.ts new file mode 100644 index 0000000..6db886e --- /dev/null +++ b/packages/tlv-account-resolution/src/pubkeyData.ts @@ -0,0 +1,75 @@ +import { + TokenTransferHookAccountDataNotFound, + TokenTransferHookInvalidPubkeyData, + TokenTransferHookPubkeyDataTooSmall, + TokenTransferHookAccountNotFound, +} from './errors'; +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> +): 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..60e21d0 --- /dev/null +++ b/packages/tlv-account-resolution/src/seeds.ts @@ -0,0 +1,154 @@ +import { + TokenTransferHookAccountDataNotFound, + TokenTransferHookInvalidSeed, +} from './errors'; +import { + type Address, + type AccountMeta, + 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..eb2fd77 --- /dev/null +++ b/packages/tlv-account-resolution/src/state.ts @@ -0,0 +1,167 @@ +import { + TokenTransferHookAccountNotFound, + TokenTransferHookInvalidPubkeyData, +} from './errors'; +import { unpackSeeds } from './seeds'; +import { unpackPubkeyData } from './pubkeyData'; +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 +): 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; +} + +/** 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; + + 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 + ); + + 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); +} 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/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"], 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..36a059a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,8 +24,13 @@ "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"],