Skip to content

Commit

Permalink
Merge branch 'master' into ak/core
Browse files Browse the repository at this point in the history
  • Loading branch information
aoikurokawa authored Oct 15, 2024
2 parents 2cb3a68 + 18e0be5 commit 0c869e3
Show file tree
Hide file tree
Showing 22 changed files with 494 additions and 250 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export type VaultStakerWithdrawalTicket = {
staker: Address;
base: Address;
vrtAmount: bigint;
minAmountOut: bigint;
slotUnstaked: bigint;
bump: number;
reserved: Array<number>;
Expand All @@ -52,6 +53,7 @@ export type VaultStakerWithdrawalTicketArgs = {
staker: Address;
base: Address;
vrtAmount: number | bigint;
minAmountOut: number | bigint;
slotUnstaked: number | bigint;
bump: number;
reserved: Array<number>;
Expand All @@ -64,6 +66,7 @@ export function getVaultStakerWithdrawalTicketEncoder(): Encoder<VaultStakerWith
['staker', getAddressEncoder()],
['base', getAddressEncoder()],
['vrtAmount', getU64Encoder()],
['minAmountOut', getU64Encoder()],
['slotUnstaked', getU64Encoder()],
['bump', getU8Encoder()],
['reserved', getArrayEncoder(getU8Encoder(), { size: 263 })],
Expand All @@ -77,6 +80,7 @@ export function getVaultStakerWithdrawalTicketDecoder(): Decoder<VaultStakerWith
['staker', getAddressDecoder()],
['base', getAddressDecoder()],
['vrtAmount', getU64Decoder()],
['minAmountOut', getU64Decoder()],
['slotUnstaked', getU64Decoder()],
['bump', getU8Decoder()],
['reserved', getArrayDecoder(getU8Decoder(), { size: 263 })],
Expand Down
54 changes: 29 additions & 25 deletions clients/js/vault_client/errors/jitoVault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,56 +74,58 @@ export const JITO_VAULT_ERROR__VAULT_SLASH_INCOMPLETE = 0x400; // 1024
export const JITO_VAULT_ERROR__VAULT_SECURITY_UNDERFLOW = 0x401; // 1025
/** SlippageError: SlippageError */
export const JITO_VAULT_ERROR__SLIPPAGE_ERROR = 0x402; // 1026
/** SlippageTooLow: SlippageTooLow */
export const JITO_VAULT_ERROR__SLIPPAGE_TOO_LOW = 0x403; // 1027
/** VaultStakerWithdrawalTicketNotWithdrawable: VaultStakerWithdrawalTicketNotWithdrawable */
export const JITO_VAULT_ERROR__VAULT_STAKER_WITHDRAWAL_TICKET_NOT_WITHDRAWABLE = 0x403; // 1027
export const JITO_VAULT_ERROR__VAULT_STAKER_WITHDRAWAL_TICKET_NOT_WITHDRAWABLE = 0x404; // 1028
/** VaultNcnSlasherTicketFailedCooldown: VaultNcnSlasherTicketFailedCooldown */
export const JITO_VAULT_ERROR__VAULT_NCN_SLASHER_TICKET_FAILED_COOLDOWN = 0x404; // 1028
export const JITO_VAULT_ERROR__VAULT_NCN_SLASHER_TICKET_FAILED_COOLDOWN = 0x405; // 1029
/** VaultNcnSlasherTicketFailedWarmup: VaultNcnSlasherTicketFailedWarmup */
export const JITO_VAULT_ERROR__VAULT_NCN_SLASHER_TICKET_FAILED_WARMUP = 0x405; // 1029
export const JITO_VAULT_ERROR__VAULT_NCN_SLASHER_TICKET_FAILED_WARMUP = 0x406; // 1030
/** VaultNcnTicketFailedCooldown: VaultNcnTicketFailedCooldown */
export const JITO_VAULT_ERROR__VAULT_NCN_TICKET_FAILED_COOLDOWN = 0x406; // 1030
export const JITO_VAULT_ERROR__VAULT_NCN_TICKET_FAILED_COOLDOWN = 0x407; // 1031
/** VaultNcnTicketFailedWarmup: VaultNcnTicketFailedWarmup */
export const JITO_VAULT_ERROR__VAULT_NCN_TICKET_FAILED_WARMUP = 0x407; // 1031
export const JITO_VAULT_ERROR__VAULT_NCN_TICKET_FAILED_WARMUP = 0x408; // 1032
/** VaultNcnTicketUnslashable: VaultNcnTicketUnslashable */
export const JITO_VAULT_ERROR__VAULT_NCN_TICKET_UNSLASHABLE = 0x408; // 1032
export const JITO_VAULT_ERROR__VAULT_NCN_TICKET_UNSLASHABLE = 0x409; // 1033
/** OperatorVaultTicketUnslashable: OperatorVaultTicketUnslashable */
export const JITO_VAULT_ERROR__OPERATOR_VAULT_TICKET_UNSLASHABLE = 0x409; // 1033
export const JITO_VAULT_ERROR__OPERATOR_VAULT_TICKET_UNSLASHABLE = 0x40a; // 1034
/** NcnOperatorStateUnslashable: NcnOperatorStateUnslashable */
export const JITO_VAULT_ERROR__NCN_OPERATOR_STATE_UNSLASHABLE = 0x40a; // 1034
export const JITO_VAULT_ERROR__NCN_OPERATOR_STATE_UNSLASHABLE = 0x40b; // 1035
/** VaultNcnSlasherTicketUnslashable: VaultNcnSlasherTicketUnslashable */
export const JITO_VAULT_ERROR__VAULT_NCN_SLASHER_TICKET_UNSLASHABLE = 0x40b; // 1035
export const JITO_VAULT_ERROR__VAULT_NCN_SLASHER_TICKET_UNSLASHABLE = 0x40c; // 1036
/** NcnVaultTicketUnslashable: NcnVaultTicketUnslashable */
export const JITO_VAULT_ERROR__NCN_VAULT_TICKET_UNSLASHABLE = 0x40c; // 1036
export const JITO_VAULT_ERROR__NCN_VAULT_TICKET_UNSLASHABLE = 0x40d; // 1037
/** NcnVaultSlasherTicketUnslashable: NcnVaultSlasherTicketUnslashable */
export const JITO_VAULT_ERROR__NCN_VAULT_SLASHER_TICKET_UNSLASHABLE = 0x40d; // 1037
export const JITO_VAULT_ERROR__NCN_VAULT_SLASHER_TICKET_UNSLASHABLE = 0x40e; // 1038
/** VaultMaxSlashedPerOperatorExceeded: VaultMaxSlashedPerOperatorExceeded */
export const JITO_VAULT_ERROR__VAULT_MAX_SLASHED_PER_OPERATOR_EXCEEDED = 0x40e; // 1038
export const JITO_VAULT_ERROR__VAULT_MAX_SLASHED_PER_OPERATOR_EXCEEDED = 0x40f; // 1039
/** VaultStakerWithdrawalTicketInvalidStaker: VaultStakerWithdrawalTicketInvalidStaker */
export const JITO_VAULT_ERROR__VAULT_STAKER_WITHDRAWAL_TICKET_INVALID_STAKER = 0x40f; // 1039
export const JITO_VAULT_ERROR__VAULT_STAKER_WITHDRAWAL_TICKET_INVALID_STAKER = 0x410; // 1040
/** SlasherOverflow: SlasherOverflow */
export const JITO_VAULT_ERROR__SLASHER_OVERFLOW = 0x410; // 1040
export const JITO_VAULT_ERROR__SLASHER_OVERFLOW = 0x411; // 1041
/** NcnOverflow: NcnOverflow */
export const JITO_VAULT_ERROR__NCN_OVERFLOW = 0x411; // 1041
export const JITO_VAULT_ERROR__NCN_OVERFLOW = 0x412; // 1042
/** OperatorOverflow: OperatorOverflow */
export const JITO_VAULT_ERROR__OPERATOR_OVERFLOW = 0x412; // 1042
export const JITO_VAULT_ERROR__OPERATOR_OVERFLOW = 0x413; // 1043
/** VaultDelegationZero: VaultDelegationZero */
export const JITO_VAULT_ERROR__VAULT_DELEGATION_ZERO = 0x413; // 1043
export const JITO_VAULT_ERROR__VAULT_DELEGATION_ZERO = 0x414; // 1044
/** VaultCooldownZero: VaultCooldownZero */
export const JITO_VAULT_ERROR__VAULT_COOLDOWN_ZERO = 0x414; // 1044
export const JITO_VAULT_ERROR__VAULT_COOLDOWN_ZERO = 0x415; // 1045
/** VaultBurnZero: VaultBurnZero */
export const JITO_VAULT_ERROR__VAULT_BURN_ZERO = 0x415; // 1045
export const JITO_VAULT_ERROR__VAULT_BURN_ZERO = 0x416; // 1046
/** VaultEnqueueWithdrawalAmountZero: VaultEnqueueWithdrawalAmountZero */
export const JITO_VAULT_ERROR__VAULT_ENQUEUE_WITHDRAWAL_AMOUNT_ZERO = 0x416; // 1046
export const JITO_VAULT_ERROR__VAULT_ENQUEUE_WITHDRAWAL_AMOUNT_ZERO = 0x417; // 1047
/** VaultMintZero: VaultMintZero */
export const JITO_VAULT_ERROR__VAULT_MINT_ZERO = 0x417; // 1047
export const JITO_VAULT_ERROR__VAULT_MINT_ZERO = 0x418; // 1048
/** InvalidDepositor: InvalidDepositor */
export const JITO_VAULT_ERROR__INVALID_DEPOSITOR = 0x418; // 1048
export const JITO_VAULT_ERROR__INVALID_DEPOSITOR = 0x419; // 1049
/** InvalidDepositTokenAccount: InvalidDepositTokenAccount */
export const JITO_VAULT_ERROR__INVALID_DEPOSIT_TOKEN_ACCOUNT = 0x419; // 1049
export const JITO_VAULT_ERROR__INVALID_DEPOSIT_TOKEN_ACCOUNT = 0x41a; // 1050
/** NoSupportedMintBalanceChange: NoSupportedMintBalanceChange */
export const JITO_VAULT_ERROR__NO_SUPPORTED_MINT_BALANCE_CHANGE = 0x41a; // 1050
export const JITO_VAULT_ERROR__NO_SUPPORTED_MINT_BALANCE_CHANGE = 0x41b; // 1051
/** InvalidEpochLength: InvalidEpochLength */
export const JITO_VAULT_ERROR__INVALID_EPOCH_LENGTH = 0x41b; // 1051
export const JITO_VAULT_ERROR__INVALID_EPOCH_LENGTH = 0x41c; // 1052
/** ArithmeticOverflow: ArithmeticOverflow */
export const JITO_VAULT_ERROR__ARITHMETIC_OVERFLOW = 0xbb8; // 3000
/** ArithmeticUnderflow: ArithmeticUnderflow */
Expand All @@ -150,6 +152,7 @@ export type JitoVaultError =
| typeof JITO_VAULT_ERROR__OPERATOR_VAULT_TICKET_UNSLASHABLE
| typeof JITO_VAULT_ERROR__SLASHER_OVERFLOW
| typeof JITO_VAULT_ERROR__SLIPPAGE_ERROR
| typeof JITO_VAULT_ERROR__SLIPPAGE_TOO_LOW
| typeof JITO_VAULT_ERROR__VAULT_ADMIN_INVALID
| typeof JITO_VAULT_ERROR__VAULT_BURN_ZERO
| typeof JITO_VAULT_ERROR__VAULT_CAPACITY_ADMIN_INVALID
Expand Down Expand Up @@ -212,6 +215,7 @@ if (process.env.NODE_ENV !== 'production') {
[JITO_VAULT_ERROR__OPERATOR_VAULT_TICKET_UNSLASHABLE]: `OperatorVaultTicketUnslashable`,
[JITO_VAULT_ERROR__SLASHER_OVERFLOW]: `SlasherOverflow`,
[JITO_VAULT_ERROR__SLIPPAGE_ERROR]: `SlippageError`,
[JITO_VAULT_ERROR__SLIPPAGE_TOO_LOW]: `SlippageTooLow`,
[JITO_VAULT_ERROR__VAULT_ADMIN_INVALID]: `VaultAdminInvalid`,
[JITO_VAULT_ERROR__VAULT_BURN_ZERO]: `VaultBurnZero`,
[JITO_VAULT_ERROR__VAULT_CAPACITY_ADMIN_INVALID]: `VaultCapacityAdminInvalid`,
Expand Down
29 changes: 5 additions & 24 deletions clients/js/vault_client/instructions/burnWithdrawalTicket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import {
combineCodec,
getStructDecoder,
getStructEncoder,
getU64Decoder,
getU64Encoder,
getU8Decoder,
getU8Encoder,
transformEncoder,
Expand Down Expand Up @@ -106,21 +104,13 @@ export type BurnWithdrawalTicketInstruction<
]
>;

export type BurnWithdrawalTicketInstructionData = {
discriminator: number;
minAmountOut: bigint;
};
export type BurnWithdrawalTicketInstructionData = { discriminator: number };

export type BurnWithdrawalTicketInstructionDataArgs = {
minAmountOut: number | bigint;
};
export type BurnWithdrawalTicketInstructionDataArgs = {};

export function getBurnWithdrawalTicketInstructionDataEncoder(): Encoder<BurnWithdrawalTicketInstructionDataArgs> {
return transformEncoder(
getStructEncoder([
['discriminator', getU8Encoder()],
['minAmountOut', getU64Encoder()],
]),
getStructEncoder([['discriminator', getU8Encoder()]]),
(value) => ({
...value,
discriminator: BURN_WITHDRAWAL_TICKET_DISCRIMINATOR,
Expand All @@ -129,10 +119,7 @@ export function getBurnWithdrawalTicketInstructionDataEncoder(): Encoder<BurnWit
}

export function getBurnWithdrawalTicketInstructionDataDecoder(): Decoder<BurnWithdrawalTicketInstructionData> {
return getStructDecoder([
['discriminator', getU8Decoder()],
['minAmountOut', getU64Decoder()],
]);
return getStructDecoder([['discriminator', getU8Decoder()]]);
}

export function getBurnWithdrawalTicketInstructionDataCodec(): Codec<
Expand Down Expand Up @@ -172,7 +159,6 @@ export type BurnWithdrawalTicketInput<
systemProgram?: Address<TAccountSystemProgram>;
/** Signer for burning */
burnSigner?: TransactionSigner<TAccountBurnSigner>;
minAmountOut: BurnWithdrawalTicketInstructionDataArgs['minAmountOut'];
};

export function getBurnWithdrawalTicketInstruction<
Expand Down Expand Up @@ -256,9 +242,6 @@ export function getBurnWithdrawalTicketInstruction<
ResolvedAccount
>;

// Original args.
const args = { ...input };

// Resolve default values.
if (!accounts.tokenProgram.value) {
accounts.tokenProgram.value =
Expand Down Expand Up @@ -286,9 +269,7 @@ export function getBurnWithdrawalTicketInstruction<
getAccountMeta(accounts.burnSigner),
],
programAddress,
data: getBurnWithdrawalTicketInstructionDataEncoder().encode(
args as BurnWithdrawalTicketInstructionDataArgs
),
data: getBurnWithdrawalTicketInstructionDataEncoder().encode({}),
} as BurnWithdrawalTicketInstruction<
typeof JITO_VAULT_PROGRAM_ADDRESS,
TAccountConfig,
Expand Down
9 changes: 8 additions & 1 deletion clients/js/vault_client/instructions/enqueueWithdrawal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,20 @@ export type EnqueueWithdrawalInstruction<
export type EnqueueWithdrawalInstructionData = {
discriminator: number;
amount: bigint;
minAmountOut: bigint;
};

export type EnqueueWithdrawalInstructionDataArgs = { amount: number | bigint };
export type EnqueueWithdrawalInstructionDataArgs = {
amount: number | bigint;
minAmountOut: number | bigint;
};

export function getEnqueueWithdrawalInstructionDataEncoder(): Encoder<EnqueueWithdrawalInstructionDataArgs> {
return transformEncoder(
getStructEncoder([
['discriminator', getU8Encoder()],
['amount', getU64Encoder()],
['minAmountOut', getU64Encoder()],
]),
(value) => ({ ...value, discriminator: ENQUEUE_WITHDRAWAL_DISCRIMINATOR })
);
Expand All @@ -121,6 +126,7 @@ export function getEnqueueWithdrawalInstructionDataDecoder(): Decoder<EnqueueWit
return getStructDecoder([
['discriminator', getU8Decoder()],
['amount', getU64Decoder()],
['minAmountOut', getU64Decoder()],
]);
}

Expand Down Expand Up @@ -158,6 +164,7 @@ export type EnqueueWithdrawalInput<
/** Signer for burning */
burnSigner?: TransactionSigner<TAccountBurnSigner>;
amount: EnqueueWithdrawalInstructionDataArgs['amount'];
minAmountOut: EnqueueWithdrawalInstructionDataArgs['minAmountOut'];
};

export function getEnqueueWithdrawalInstruction<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub struct VaultStakerWithdrawalTicket {
)]
pub base: Pubkey,
pub vrt_amount: u64,
pub min_amount_out: u64,
pub slot_unstaked: u64,
pub bump: u8,
#[cfg_attr(feature = "serde", serde(with = "serde_with::As::<serde_with::Bytes>"))]
Expand Down
103 changes: 53 additions & 50 deletions clients/rust/vault_client/src/generated/errors/jito_vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,81 +99,84 @@ pub enum JitoVaultError {
/// 1026 - SlippageError
#[error("SlippageError")]
SlippageError = 0x402,
/// 1027 - VaultStakerWithdrawalTicketNotWithdrawable
/// 1027 - SlippageTooLow
#[error("SlippageTooLow")]
SlippageTooLow = 0x403,
/// 1028 - VaultStakerWithdrawalTicketNotWithdrawable
#[error("VaultStakerWithdrawalTicketNotWithdrawable")]
VaultStakerWithdrawalTicketNotWithdrawable = 0x403,
/// 1028 - VaultNcnSlasherTicketFailedCooldown
VaultStakerWithdrawalTicketNotWithdrawable = 0x404,
/// 1029 - VaultNcnSlasherTicketFailedCooldown
#[error("VaultNcnSlasherTicketFailedCooldown")]
VaultNcnSlasherTicketFailedCooldown = 0x404,
/// 1029 - VaultNcnSlasherTicketFailedWarmup
VaultNcnSlasherTicketFailedCooldown = 0x405,
/// 1030 - VaultNcnSlasherTicketFailedWarmup
#[error("VaultNcnSlasherTicketFailedWarmup")]
VaultNcnSlasherTicketFailedWarmup = 0x405,
/// 1030 - VaultNcnTicketFailedCooldown
VaultNcnSlasherTicketFailedWarmup = 0x406,
/// 1031 - VaultNcnTicketFailedCooldown
#[error("VaultNcnTicketFailedCooldown")]
VaultNcnTicketFailedCooldown = 0x406,
/// 1031 - VaultNcnTicketFailedWarmup
VaultNcnTicketFailedCooldown = 0x407,
/// 1032 - VaultNcnTicketFailedWarmup
#[error("VaultNcnTicketFailedWarmup")]
VaultNcnTicketFailedWarmup = 0x407,
/// 1032 - VaultNcnTicketUnslashable
VaultNcnTicketFailedWarmup = 0x408,
/// 1033 - VaultNcnTicketUnslashable
#[error("VaultNcnTicketUnslashable")]
VaultNcnTicketUnslashable = 0x408,
/// 1033 - OperatorVaultTicketUnslashable
VaultNcnTicketUnslashable = 0x409,
/// 1034 - OperatorVaultTicketUnslashable
#[error("OperatorVaultTicketUnslashable")]
OperatorVaultTicketUnslashable = 0x409,
/// 1034 - NcnOperatorStateUnslashable
OperatorVaultTicketUnslashable = 0x40A,
/// 1035 - NcnOperatorStateUnslashable
#[error("NcnOperatorStateUnslashable")]
NcnOperatorStateUnslashable = 0x40A,
/// 1035 - VaultNcnSlasherTicketUnslashable
NcnOperatorStateUnslashable = 0x40B,
/// 1036 - VaultNcnSlasherTicketUnslashable
#[error("VaultNcnSlasherTicketUnslashable")]
VaultNcnSlasherTicketUnslashable = 0x40B,
/// 1036 - NcnVaultTicketUnslashable
VaultNcnSlasherTicketUnslashable = 0x40C,
/// 1037 - NcnVaultTicketUnslashable
#[error("NcnVaultTicketUnslashable")]
NcnVaultTicketUnslashable = 0x40C,
/// 1037 - NcnVaultSlasherTicketUnslashable
NcnVaultTicketUnslashable = 0x40D,
/// 1038 - NcnVaultSlasherTicketUnslashable
#[error("NcnVaultSlasherTicketUnslashable")]
NcnVaultSlasherTicketUnslashable = 0x40D,
/// 1038 - VaultMaxSlashedPerOperatorExceeded
NcnVaultSlasherTicketUnslashable = 0x40E,
/// 1039 - VaultMaxSlashedPerOperatorExceeded
#[error("VaultMaxSlashedPerOperatorExceeded")]
VaultMaxSlashedPerOperatorExceeded = 0x40E,
/// 1039 - VaultStakerWithdrawalTicketInvalidStaker
VaultMaxSlashedPerOperatorExceeded = 0x40F,
/// 1040 - VaultStakerWithdrawalTicketInvalidStaker
#[error("VaultStakerWithdrawalTicketInvalidStaker")]
VaultStakerWithdrawalTicketInvalidStaker = 0x40F,
/// 1040 - SlasherOverflow
VaultStakerWithdrawalTicketInvalidStaker = 0x410,
/// 1041 - SlasherOverflow
#[error("SlasherOverflow")]
SlasherOverflow = 0x410,
/// 1041 - NcnOverflow
SlasherOverflow = 0x411,
/// 1042 - NcnOverflow
#[error("NcnOverflow")]
NcnOverflow = 0x411,
/// 1042 - OperatorOverflow
NcnOverflow = 0x412,
/// 1043 - OperatorOverflow
#[error("OperatorOverflow")]
OperatorOverflow = 0x412,
/// 1043 - VaultDelegationZero
OperatorOverflow = 0x413,
/// 1044 - VaultDelegationZero
#[error("VaultDelegationZero")]
VaultDelegationZero = 0x413,
/// 1044 - VaultCooldownZero
VaultDelegationZero = 0x414,
/// 1045 - VaultCooldownZero
#[error("VaultCooldownZero")]
VaultCooldownZero = 0x414,
/// 1045 - VaultBurnZero
VaultCooldownZero = 0x415,
/// 1046 - VaultBurnZero
#[error("VaultBurnZero")]
VaultBurnZero = 0x415,
/// 1046 - VaultEnqueueWithdrawalAmountZero
VaultBurnZero = 0x416,
/// 1047 - VaultEnqueueWithdrawalAmountZero
#[error("VaultEnqueueWithdrawalAmountZero")]
VaultEnqueueWithdrawalAmountZero = 0x416,
/// 1047 - VaultMintZero
VaultEnqueueWithdrawalAmountZero = 0x417,
/// 1048 - VaultMintZero
#[error("VaultMintZero")]
VaultMintZero = 0x417,
/// 1048 - InvalidDepositor
VaultMintZero = 0x418,
/// 1049 - InvalidDepositor
#[error("InvalidDepositor")]
InvalidDepositor = 0x418,
/// 1049 - InvalidDepositTokenAccount
InvalidDepositor = 0x419,
/// 1050 - InvalidDepositTokenAccount
#[error("InvalidDepositTokenAccount")]
InvalidDepositTokenAccount = 0x419,
/// 1050 - NoSupportedMintBalanceChange
InvalidDepositTokenAccount = 0x41A,
/// 1051 - NoSupportedMintBalanceChange
#[error("NoSupportedMintBalanceChange")]
NoSupportedMintBalanceChange = 0x41A,
/// 1051 - InvalidEpochLength
NoSupportedMintBalanceChange = 0x41B,
/// 1052 - InvalidEpochLength
#[error("InvalidEpochLength")]
InvalidEpochLength = 0x41B,
InvalidEpochLength = 0x41C,
/// 3000 - ArithmeticOverflow
#[error("ArithmeticOverflow")]
ArithmeticOverflow = 0xBB8,
Expand Down
Loading

0 comments on commit 0c869e3

Please sign in to comment.