mirror of https://github.com/certusone/oyster.git
Merge branch 'main' into feature/m
This commit is contained in:
commit
37656808e0
|
@ -6,7 +6,7 @@ header.ant-layout-header.App-Bar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center !important;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
|
|
||||||
.nav-burger {
|
.nav-burger {
|
||||||
|
@ -30,6 +30,9 @@ header.ant-layout-header.App-Bar {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: auto;
|
height: auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
button.app-bar-item {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
.app-bar-item {
|
.app-bar-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0 30px;
|
padding: 0 30px;
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { useWallet, WALLET_PROVIDERS } from '@oyster/common';
|
||||||
|
import { shortenAddress } from '@oyster/common';
|
||||||
|
|
||||||
|
export const CurrentUserWalletBadge = (props: { showDisconnect?: boolean }) => {
|
||||||
|
const { wallet, disconnect } = useWallet();
|
||||||
|
|
||||||
|
if (!wallet || !wallet.publicKey) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="wallet-wrapper">
|
||||||
|
<div className="wallet-key">
|
||||||
|
<img
|
||||||
|
alt={'icon'}
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
src={WALLET_PROVIDERS.filter(p => p.name === 'Sollet')[0]?.icon}
|
||||||
|
style={{ marginRight: 8 }}
|
||||||
|
/>
|
||||||
|
{shortenAddress(`${wallet.publicKey}`)}
|
||||||
|
{props.showDisconnect && (
|
||||||
|
<span className={'disconnect'} onClick={() => disconnect()}>
|
||||||
|
X
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -13,6 +13,7 @@ import { TokenSelectModal } from '../TokenSelectModal';
|
||||||
import { chainToName } from '../../utils/assets';
|
import { chainToName } from '../../utils/assets';
|
||||||
import { TokenChain } from '../TokenDisplay/tokenChain';
|
import { TokenChain } from '../TokenDisplay/tokenChain';
|
||||||
import { EthereumConnect } from '../EthereumConnect';
|
import { EthereumConnect } from '../EthereumConnect';
|
||||||
|
import { CurrentUserWalletBadge } from '../CurrentUserWalletBadge';
|
||||||
|
|
||||||
export function Input(props: {
|
export function Input(props: {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -106,7 +107,10 @@ export function Input(props: {
|
||||||
</div>
|
</div>
|
||||||
{props.chain === ASSET_CHAIN.Ethereum ? (
|
{props.chain === ASSET_CHAIN.Ethereum ? (
|
||||||
<EthereumConnect />
|
<EthereumConnect />
|
||||||
) : (<ConnectButton type="text" size="large" allowWalletChange={true} />
|
) : connected ? (
|
||||||
|
<CurrentUserWalletBadge showDisconnect={true} />
|
||||||
|
) : (
|
||||||
|
<ConnectButton type="text" size="large" allowWalletChange={true} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -145,7 +145,11 @@ export const RecentTransactionsTable = () => {
|
||||||
render(text: string, record: any) {
|
render(text: string, record: any) {
|
||||||
return {
|
return {
|
||||||
props: { style: {} },
|
props: { style: {} },
|
||||||
children: <span className={`${record.status?.toLowerCase()}`}>{record.status}</span>,
|
children: (
|
||||||
|
<span className={`${record.status?.toLowerCase()}`}>
|
||||||
|
{record.status}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -65,10 +65,7 @@ const queryWrappedMetaTransactions = async (
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let wh = WormholeFactory.connect(
|
let wh = WormholeFactory.connect(programIds().wormhole.bridge, provider);
|
||||||
programIds().wormhole.bridge,
|
|
||||||
provider,
|
|
||||||
);
|
|
||||||
const resp = await (connection as any)._rpcRequest('getProgramAccounts', [
|
const resp = await (connection as any)._rpcRequest('getProgramAccounts', [
|
||||||
WORMHOLE_PROGRAM_ID.toBase58(),
|
WORMHOLE_PROGRAM_ID.toBase58(),
|
||||||
{
|
{
|
||||||
|
@ -227,7 +224,6 @@ export const useWormholeTransactions = () => {
|
||||||
bridge,
|
bridge,
|
||||||
).then(() => setLoading(false));
|
).then(() => setLoading(false));
|
||||||
})();
|
})();
|
||||||
|
|
||||||
}, [connection, setTransfers]);
|
}, [connection, setTransfers]);
|
||||||
|
|
||||||
const coingeckoTimer = useRef<number>(0);
|
const coingeckoTimer = useRef<number>(0);
|
||||||
|
|
|
@ -158,9 +158,7 @@ export const HomeView = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className={'description-title'}>Bridge in any direction</div>
|
<div className={'description-title'}>Bridge in any direction</div>
|
||||||
<div className={'description-text'}>
|
<div className={'description-text'}>
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis
|
|
||||||
nisi at praesent sed sollicitudin ullamcorper malesuada in.
|
|
||||||
Molestie sed morbi vitae in amet ultrices.
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'home-description-item'}>
|
<div className={'home-description-item'}>
|
||||||
|
@ -169,9 +167,7 @@ export const HomeView = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className={'description-title'}>Staking & Validation</div>
|
<div className={'description-title'}>Staking & Validation</div>
|
||||||
<div className={'description-text'}>
|
<div className={'description-text'}>
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis
|
|
||||||
nisi at praesent sed sollicitudin ullamcorper malesuada in.
|
|
||||||
Molestie sed morbi vitae in amet ultrices.
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'home-description-item'}>
|
<div className={'home-description-item'}>
|
||||||
|
@ -180,9 +176,7 @@ export const HomeView = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className={'description-title'}>Layers and Capabilities</div>
|
<div className={'description-title'}>Layers and Capabilities</div>
|
||||||
<div className={'description-text'}>
|
<div className={'description-text'}>
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis
|
|
||||||
nisi at praesent sed sollicitudin ullamcorper malesuada in.
|
|
||||||
Molestie sed morbi vitae in amet ultrices.
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -65,27 +65,17 @@ export function approve(
|
||||||
const transferAuthority = existingTransferAuthority || new Account();
|
const transferAuthority = existingTransferAuthority || new Account();
|
||||||
const delegateKey = delegate ?? transferAuthority.publicKey;
|
const delegateKey = delegate ?? transferAuthority.publicKey;
|
||||||
|
|
||||||
const instruction = Token.createApproveInstruction(
|
instructions.push(
|
||||||
|
Token.createApproveInstruction(
|
||||||
tokenProgram,
|
tokenProgram,
|
||||||
account,
|
account,
|
||||||
delegateKey,
|
delegate ?? transferAuthority.publicKey,
|
||||||
owner,
|
owner,
|
||||||
[],
|
[],
|
||||||
amount,
|
amount,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Temp. workaround for a bug in Token.createApproveInstruction which doesn't add the delegate account to signers
|
|
||||||
instruction.keys = instruction.keys.map(k =>
|
|
||||||
k.pubkey.equals(delegateKey)
|
|
||||||
? {
|
|
||||||
...k,
|
|
||||||
isSigner: true,
|
|
||||||
}
|
|
||||||
: k,
|
|
||||||
);
|
|
||||||
|
|
||||||
instructions.push(instruction);
|
|
||||||
|
|
||||||
if (autoRevoke) {
|
if (autoRevoke) {
|
||||||
cleanupInstructions.push(
|
cleanupInstructions.push(
|
||||||
Token.createRevokeInstruction(tokenProgram, account, owner, []),
|
Token.createRevokeInstruction(tokenProgram, account, owner, []),
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
} from '@solana/web3.js';
|
} from '@solana/web3.js';
|
||||||
import { contexts, utils, models, ParsedAccount } from '@oyster/common';
|
import { contexts, utils, models, ParsedAccount } from '@oyster/common';
|
||||||
import {
|
import {
|
||||||
|
GOVERNANCE_AUTHORITY_SEED,
|
||||||
CustomSingleSignerTimelockTransactionLayout,
|
CustomSingleSignerTimelockTransactionLayout,
|
||||||
TimelockSet,
|
TimelockSet,
|
||||||
TimelockState,
|
TimelockState,
|
||||||
|
@ -50,7 +51,7 @@ export const addCustomSingleSignerTransaction = async (
|
||||||
});
|
});
|
||||||
|
|
||||||
const [authority] = await PublicKey.findProgramAddress(
|
const [authority] = await PublicKey.findProgramAddress(
|
||||||
[proposal.pubkey.toBuffer()],
|
[Buffer.from(GOVERNANCE_AUTHORITY_SEED), proposal.pubkey.toBuffer()],
|
||||||
PROGRAM_IDS.timelock.programId,
|
PROGRAM_IDS.timelock.programId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,11 @@ import {
|
||||||
actions,
|
actions,
|
||||||
} from '@oyster/common';
|
} from '@oyster/common';
|
||||||
|
|
||||||
import { TimelockSet, TimelockState } from '../models/timelock';
|
import {
|
||||||
|
GOVERNANCE_AUTHORITY_SEED,
|
||||||
|
TimelockSet,
|
||||||
|
TimelockState,
|
||||||
|
} from '../models/timelock';
|
||||||
import { AccountLayout } from '@solana/spl-token';
|
import { AccountLayout } from '@solana/spl-token';
|
||||||
import { addSignerInstruction } from '../models/addSigner';
|
import { addSignerInstruction } from '../models/addSigner';
|
||||||
const { createTokenAccount } = actions;
|
const { createTokenAccount } = actions;
|
||||||
|
@ -47,7 +51,7 @@ export const addSigner = async (
|
||||||
);
|
);
|
||||||
|
|
||||||
const [mintAuthority] = await PublicKey.findProgramAddress(
|
const [mintAuthority] = await PublicKey.findProgramAddress(
|
||||||
[proposal.pubkey.toBuffer()],
|
[Buffer.from(GOVERNANCE_AUTHORITY_SEED), proposal.pubkey.toBuffer()],
|
||||||
PROGRAM_IDS.timelock.programId,
|
PROGRAM_IDS.timelock.programId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { contexts, utils, actions, ParsedAccount } from '@oyster/common';
|
||||||
import { AccountLayout, MintLayout } from '@solana/spl-token';
|
import { AccountLayout, MintLayout } from '@solana/spl-token';
|
||||||
import { initTimelockSetInstruction } from '../models/initTimelockSet';
|
import { initTimelockSetInstruction } from '../models/initTimelockSet';
|
||||||
import {
|
import {
|
||||||
|
GOVERNANCE_AUTHORITY_SEED,
|
||||||
TimelockConfig,
|
TimelockConfig,
|
||||||
TimelockSetLayout,
|
TimelockSetLayout,
|
||||||
TimelockStateLayout,
|
TimelockStateLayout,
|
||||||
|
@ -45,7 +46,7 @@ export const createProposal = async (
|
||||||
connection,
|
connection,
|
||||||
useGovernance
|
useGovernance
|
||||||
? timelockConfig.info.governanceMint
|
? timelockConfig.info.governanceMint
|
||||||
: timelockConfig.info.councilMint,
|
: timelockConfig.info.councilMint!,
|
||||||
)
|
)
|
||||||
).decimals;
|
).decimals;
|
||||||
|
|
||||||
|
@ -135,7 +136,7 @@ export const createProposal = async (
|
||||||
sourceHoldingAccount,
|
sourceHoldingAccount,
|
||||||
useGovernance
|
useGovernance
|
||||||
? timelockConfig.info.governanceMint
|
? timelockConfig.info.governanceMint
|
||||||
: timelockConfig.info.councilMint,
|
: timelockConfig.info.councilMint!,
|
||||||
authority,
|
authority,
|
||||||
description,
|
description,
|
||||||
name,
|
name,
|
||||||
|
@ -205,7 +206,10 @@ async function getAssociatedAccountsAndInstructions(
|
||||||
const PROGRAM_IDS = utils.programIds();
|
const PROGRAM_IDS = utils.programIds();
|
||||||
|
|
||||||
const [authority] = await PublicKey.findProgramAddress(
|
const [authority] = await PublicKey.findProgramAddress(
|
||||||
[newProposalKey.publicKey.toBuffer()],
|
[
|
||||||
|
Buffer.from(GOVERNANCE_AUTHORITY_SEED),
|
||||||
|
newProposalKey.publicKey.toBuffer(),
|
||||||
|
],
|
||||||
PROGRAM_IDS.timelock.programId,
|
PROGRAM_IDS.timelock.programId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -342,7 +346,7 @@ async function getAssociatedAccountsAndInstructions(
|
||||||
accountRentExempt,
|
accountRentExempt,
|
||||||
useGovernance
|
useGovernance
|
||||||
? timelockConfig.info.governanceMint
|
? timelockConfig.info.governanceMint
|
||||||
: timelockConfig.info.councilMint,
|
: timelockConfig.info.councilMint!,
|
||||||
authority,
|
authority,
|
||||||
holdingSigners,
|
holdingSigners,
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,7 +12,12 @@ import {
|
||||||
actions,
|
actions,
|
||||||
} from '@oyster/common';
|
} from '@oyster/common';
|
||||||
|
|
||||||
import { TimelockConfig, TimelockSet, TimelockState } from '../models/timelock';
|
import {
|
||||||
|
GOVERNANCE_AUTHORITY_SEED,
|
||||||
|
TimelockConfig,
|
||||||
|
TimelockSet,
|
||||||
|
TimelockState,
|
||||||
|
} from '../models/timelock';
|
||||||
|
|
||||||
import { AccountLayout } from '@solana/spl-token';
|
import { AccountLayout } from '@solana/spl-token';
|
||||||
|
|
||||||
|
@ -66,6 +71,7 @@ export const depositSourceTokensAndVote = async (
|
||||||
|
|
||||||
const [governanceVotingRecord] = await PublicKey.findProgramAddress(
|
const [governanceVotingRecord] = await PublicKey.findProgramAddress(
|
||||||
[
|
[
|
||||||
|
Buffer.from(GOVERNANCE_AUTHORITY_SEED),
|
||||||
PROGRAM_IDS.timelock.programId.toBuffer(),
|
PROGRAM_IDS.timelock.programId.toBuffer(),
|
||||||
proposal.pubkey.toBuffer(),
|
proposal.pubkey.toBuffer(),
|
||||||
existingVoteAccount.toBuffer(),
|
existingVoteAccount.toBuffer(),
|
||||||
|
@ -107,7 +113,7 @@ export const depositSourceTokensAndVote = async (
|
||||||
}
|
}
|
||||||
|
|
||||||
const [mintAuthority] = await PublicKey.findProgramAddress(
|
const [mintAuthority] = await PublicKey.findProgramAddress(
|
||||||
[proposal.pubkey.toBuffer()],
|
[Buffer.from(GOVERNANCE_AUTHORITY_SEED), proposal.pubkey.toBuffer()],
|
||||||
PROGRAM_IDS.timelock.programId,
|
PROGRAM_IDS.timelock.programId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ export const mintSourceTokens = async (
|
||||||
accountRentExempt,
|
accountRentExempt,
|
||||||
useGovernance
|
useGovernance
|
||||||
? timelockConfig.info.governanceMint
|
? timelockConfig.info.governanceMint
|
||||||
: timelockConfig.info.councilMint,
|
: timelockConfig.info.councilMint!,
|
||||||
e.owner,
|
e.owner,
|
||||||
signers,
|
signers,
|
||||||
);
|
);
|
||||||
|
@ -55,7 +55,7 @@ export const mintSourceTokens = async (
|
||||||
PROGRAM_IDS.token,
|
PROGRAM_IDS.token,
|
||||||
useGovernance
|
useGovernance
|
||||||
? timelockConfig.info.governanceMint
|
? timelockConfig.info.governanceMint
|
||||||
: timelockConfig.info.councilMint,
|
: timelockConfig.info.councilMint!,
|
||||||
e.sourceAccount,
|
e.sourceAccount,
|
||||||
wallet.publicKey,
|
wallet.publicKey,
|
||||||
[],
|
[],
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { contexts, utils, actions } from '@oyster/common';
|
||||||
|
|
||||||
import { AccountLayout, MintLayout, Token } from '@solana/spl-token';
|
import { AccountLayout, MintLayout, Token } from '@solana/spl-token';
|
||||||
import {
|
import {
|
||||||
|
GOVERNANCE_AUTHORITY_SEED,
|
||||||
ConsensusAlgorithm,
|
ConsensusAlgorithm,
|
||||||
ExecutionType,
|
ExecutionType,
|
||||||
TimelockConfig,
|
TimelockConfig,
|
||||||
|
@ -26,6 +27,7 @@ export const registerProgramGovernance = async (
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
wallet: any,
|
wallet: any,
|
||||||
uninitializedTimelockConfig: Partial<TimelockConfig>,
|
uninitializedTimelockConfig: Partial<TimelockConfig>,
|
||||||
|
useCouncil: boolean,
|
||||||
): Promise<PublicKey> => {
|
): Promise<PublicKey> => {
|
||||||
const PROGRAM_IDS = utils.programIds();
|
const PROGRAM_IDS = utils.programIds();
|
||||||
let signers: Account[] = [];
|
let signers: Account[] = [];
|
||||||
|
@ -43,7 +45,7 @@ export const registerProgramGovernance = async (
|
||||||
if (!uninitializedTimelockConfig.program)
|
if (!uninitializedTimelockConfig.program)
|
||||||
uninitializedTimelockConfig.program = new Account().publicKey; // Random generation if none given
|
uninitializedTimelockConfig.program = new Account().publicKey; // Random generation if none given
|
||||||
|
|
||||||
if (!uninitializedTimelockConfig.councilMint) {
|
if (!uninitializedTimelockConfig.councilMint && useCouncil) {
|
||||||
// Initialize the mint, an account for the admin, and give them one council token
|
// Initialize the mint, an account for the admin, and give them one council token
|
||||||
// to start their lives with.
|
// to start their lives with.
|
||||||
uninitializedTimelockConfig.councilMint = createMint(
|
uninitializedTimelockConfig.councilMint = createMint(
|
||||||
|
@ -111,11 +113,16 @@ export const registerProgramGovernance = async (
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const councilMintSeed = uninitializedTimelockConfig.councilMint
|
||||||
|
? uninitializedTimelockConfig.councilMint.toBuffer()
|
||||||
|
: Buffer.from('');
|
||||||
|
|
||||||
const [timelockConfigKey] = await PublicKey.findProgramAddress(
|
const [timelockConfigKey] = await PublicKey.findProgramAddress(
|
||||||
[
|
[
|
||||||
|
Buffer.from(GOVERNANCE_AUTHORITY_SEED),
|
||||||
PROGRAM_IDS.timelock.programId.toBuffer(),
|
PROGRAM_IDS.timelock.programId.toBuffer(),
|
||||||
uninitializedTimelockConfig.governanceMint.toBuffer(),
|
uninitializedTimelockConfig.governanceMint.toBuffer(),
|
||||||
uninitializedTimelockConfig.councilMint.toBuffer(),
|
councilMintSeed,
|
||||||
uninitializedTimelockConfig.program.toBuffer(),
|
uninitializedTimelockConfig.program.toBuffer(),
|
||||||
],
|
],
|
||||||
PROGRAM_IDS.timelock.programId,
|
PROGRAM_IDS.timelock.programId,
|
||||||
|
@ -126,8 +133,8 @@ export const registerProgramGovernance = async (
|
||||||
timelockConfigKey,
|
timelockConfigKey,
|
||||||
uninitializedTimelockConfig.program,
|
uninitializedTimelockConfig.program,
|
||||||
uninitializedTimelockConfig.governanceMint,
|
uninitializedTimelockConfig.governanceMint,
|
||||||
uninitializedTimelockConfig.councilMint,
|
|
||||||
wallet.publicKey,
|
wallet.publicKey,
|
||||||
|
uninitializedTimelockConfig.councilMint,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
instructions.push(
|
instructions.push(
|
||||||
|
@ -135,7 +142,7 @@ export const registerProgramGovernance = async (
|
||||||
timelockConfigKey,
|
timelockConfigKey,
|
||||||
uninitializedTimelockConfig.program,
|
uninitializedTimelockConfig.program,
|
||||||
uninitializedTimelockConfig.governanceMint,
|
uninitializedTimelockConfig.governanceMint,
|
||||||
uninitializedTimelockConfig.councilMint,
|
|
||||||
uninitializedTimelockConfig.consensusAlgorithm ||
|
uninitializedTimelockConfig.consensusAlgorithm ||
|
||||||
ConsensusAlgorithm.Majority,
|
ConsensusAlgorithm.Majority,
|
||||||
uninitializedTimelockConfig.executionType || ExecutionType.Independent,
|
uninitializedTimelockConfig.executionType || ExecutionType.Independent,
|
||||||
|
@ -145,6 +152,7 @@ export const registerProgramGovernance = async (
|
||||||
uninitializedTimelockConfig.minimumSlotWaitingPeriod || new BN(0),
|
uninitializedTimelockConfig.minimumSlotWaitingPeriod || new BN(0),
|
||||||
uninitializedTimelockConfig.timeLimit || new BN(0),
|
uninitializedTimelockConfig.timeLimit || new BN(0),
|
||||||
uninitializedTimelockConfig.name || '',
|
uninitializedTimelockConfig.name || '',
|
||||||
|
uninitializedTimelockConfig.councilMint,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
} from '@solana/web3.js';
|
} from '@solana/web3.js';
|
||||||
import { contexts, utils, models, ParsedAccount } from '@oyster/common';
|
import { contexts, utils, models, ParsedAccount } from '@oyster/common';
|
||||||
|
|
||||||
import { TimelockSet } from '../models/timelock';
|
import { GOVERNANCE_AUTHORITY_SEED, TimelockSet } from '../models/timelock';
|
||||||
import { removeSignerInstruction } from '../models/removeSigner';
|
import { removeSignerInstruction } from '../models/removeSigner';
|
||||||
const { sendTransaction } = contexts.Connection;
|
const { sendTransaction } = contexts.Connection;
|
||||||
const { notify } = utils;
|
const { notify } = utils;
|
||||||
|
@ -25,7 +25,7 @@ export const removeSigner = async (
|
||||||
let instructions: TransactionInstruction[] = [];
|
let instructions: TransactionInstruction[] = [];
|
||||||
|
|
||||||
const [mintAuthority] = await PublicKey.findProgramAddress(
|
const [mintAuthority] = await PublicKey.findProgramAddress(
|
||||||
[proposal.pubkey.toBuffer()],
|
[Buffer.from(GOVERNANCE_AUTHORITY_SEED), proposal.pubkey.toBuffer()],
|
||||||
PROGRAM_IDS.timelock.programId,
|
PROGRAM_IDS.timelock.programId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,11 @@ import {
|
||||||
} from '@solana/web3.js';
|
} from '@solana/web3.js';
|
||||||
import { contexts, utils, models, ParsedAccount } from '@oyster/common';
|
import { contexts, utils, models, ParsedAccount } from '@oyster/common';
|
||||||
|
|
||||||
import { TimelockSet, TimelockState } from '../models/timelock';
|
import {
|
||||||
|
GOVERNANCE_AUTHORITY_SEED,
|
||||||
|
TimelockSet,
|
||||||
|
TimelockState,
|
||||||
|
} from '../models/timelock';
|
||||||
import { signInstruction } from '../models/sign';
|
import { signInstruction } from '../models/sign';
|
||||||
|
|
||||||
const { sendTransaction } = contexts.Connection;
|
const { sendTransaction } = contexts.Connection;
|
||||||
|
@ -26,7 +30,7 @@ export const sign = async (
|
||||||
let instructions: TransactionInstruction[] = [];
|
let instructions: TransactionInstruction[] = [];
|
||||||
|
|
||||||
const [mintAuthority] = await PublicKey.findProgramAddress(
|
const [mintAuthority] = await PublicKey.findProgramAddress(
|
||||||
[proposal.pubkey.toBuffer()],
|
[Buffer.from(GOVERNANCE_AUTHORITY_SEED), proposal.pubkey.toBuffer()],
|
||||||
PROGRAM_IDS.timelock.programId,
|
PROGRAM_IDS.timelock.programId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
} from '@oyster/common';
|
} from '@oyster/common';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
GOVERNANCE_AUTHORITY_SEED,
|
||||||
TimelockSet,
|
TimelockSet,
|
||||||
TimelockState,
|
TimelockState,
|
||||||
TimelockStateStatus,
|
TimelockStateStatus,
|
||||||
|
@ -79,7 +80,7 @@ export const withdrawVotingTokens = async (
|
||||||
}
|
}
|
||||||
|
|
||||||
const [mintAuthority] = await PublicKey.findProgramAddress(
|
const [mintAuthority] = await PublicKey.findProgramAddress(
|
||||||
[proposal.pubkey.toBuffer()],
|
[Buffer.from(GOVERNANCE_AUTHORITY_SEED), proposal.pubkey.toBuffer()],
|
||||||
PROGRAM_IDS.timelock.programId,
|
PROGRAM_IDS.timelock.programId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -117,6 +118,7 @@ export const withdrawVotingTokens = async (
|
||||||
|
|
||||||
const [governanceVotingRecord] = await PublicKey.findProgramAddress(
|
const [governanceVotingRecord] = await PublicKey.findProgramAddress(
|
||||||
[
|
[
|
||||||
|
Buffer.from(GOVERNANCE_AUTHORITY_SEED),
|
||||||
PROGRAM_IDS.timelock.programId.toBuffer(),
|
PROGRAM_IDS.timelock.programId.toBuffer(),
|
||||||
proposal.pubkey.toBuffer(),
|
proposal.pubkey.toBuffer(),
|
||||||
existingVoteAccount.toBuffer(),
|
existingVoteAccount.toBuffer(),
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default function MintSourceTokens({
|
||||||
const connection = useConnection();
|
const connection = useConnection();
|
||||||
const mintKey = useGovernance
|
const mintKey = useGovernance
|
||||||
? timelockConfig.info.governanceMint
|
? timelockConfig.info.governanceMint
|
||||||
: timelockConfig.info.councilMint;
|
: timelockConfig.info.councilMint!;
|
||||||
const mint = useMint(mintKey);
|
const mint = useMint(mintKey);
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
|
|
||||||
|
|
|
@ -13,16 +13,16 @@ import * as Layout from '../utils/layout';
|
||||||
/// program account key, governance mint key, council mint key, and timelock program account key.
|
/// program account key, governance mint key, council mint key, and timelock program account key.
|
||||||
/// 1. `[]` Program account to tie this config to.
|
/// 1. `[]` Program account to tie this config to.
|
||||||
/// 2. `[]` Governance mint to tie this config to
|
/// 2. `[]` Governance mint to tie this config to
|
||||||
/// 3. `[]` Council mint [optional] to tie this config to [Pass in 0s otherwise]
|
/// 3. `[]` Payer
|
||||||
/// 4. `[]` Payer
|
/// 4. `[]` Timelock program pub key.
|
||||||
/// 6. `[]` Timelock program pub key.
|
/// 5. `[]` System account.
|
||||||
/// 7. `[]` System account.
|
/// 6. `[]` Council mint [optional] to tie this config to [Optional]
|
||||||
export const createEmptyTimelockConfigInstruction = (
|
export const createEmptyTimelockConfigInstruction = (
|
||||||
timelockConfigAccount: PublicKey,
|
timelockConfigAccount: PublicKey,
|
||||||
programAccount: PublicKey,
|
programAccount: PublicKey,
|
||||||
governanceMint: PublicKey,
|
governanceMint: PublicKey,
|
||||||
councilMint: PublicKey,
|
|
||||||
payer: PublicKey,
|
payer: PublicKey,
|
||||||
|
councilMint?: PublicKey,
|
||||||
): TransactionInstruction => {
|
): TransactionInstruction => {
|
||||||
const PROGRAM_IDS = utils.programIds();
|
const PROGRAM_IDS = utils.programIds();
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ export const createEmptyTimelockConfigInstruction = (
|
||||||
{ pubkey: timelockConfigAccount, isSigner: false, isWritable: false },
|
{ pubkey: timelockConfigAccount, isSigner: false, isWritable: false },
|
||||||
{ pubkey: programAccount, isSigner: false, isWritable: false },
|
{ pubkey: programAccount, isSigner: false, isWritable: false },
|
||||||
{ pubkey: governanceMint, isSigner: false, isWritable: false },
|
{ pubkey: governanceMint, isSigner: false, isWritable: false },
|
||||||
{ pubkey: councilMint, isSigner: false, isWritable: false },
|
|
||||||
{ pubkey: payer, isSigner: true, isWritable: false },
|
{ pubkey: payer, isSigner: true, isWritable: false },
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -51,6 +50,11 @@ export const createEmptyTimelockConfigInstruction = (
|
||||||
},
|
},
|
||||||
{ pubkey: PROGRAM_IDS.system, isSigner: false, isWritable: false },
|
{ pubkey: PROGRAM_IDS.system, isSigner: false, isWritable: false },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (councilMint) {
|
||||||
|
keys.push({ pubkey: councilMint, isSigner: false, isWritable: false });
|
||||||
|
}
|
||||||
|
|
||||||
return new TransactionInstruction({
|
return new TransactionInstruction({
|
||||||
keys,
|
keys,
|
||||||
programId: PROGRAM_IDS.timelock.programId,
|
programId: PROGRAM_IDS.timelock.programId,
|
||||||
|
|
|
@ -55,7 +55,7 @@ export const depositSourceTokensInstruction = (
|
||||||
{ pubkey: sourceHoldingAccount, isSigner: false, isWritable: true },
|
{ pubkey: sourceHoldingAccount, isSigner: false, isWritable: true },
|
||||||
{ pubkey: votingMint, isSigner: false, isWritable: true },
|
{ pubkey: votingMint, isSigner: false, isWritable: true },
|
||||||
{ pubkey: timelockSetAccount, isSigner: false, isWritable: false },
|
{ pubkey: timelockSetAccount, isSigner: false, isWritable: false },
|
||||||
{ pubkey: transferAuthority, isSigner: false, isWritable: false },
|
{ pubkey: transferAuthority, isSigner: true, isWritable: false },
|
||||||
{ pubkey: mintAuthority, isSigner: false, isWritable: false },
|
{ pubkey: mintAuthority, isSigner: false, isWritable: false },
|
||||||
{ pubkey: PROGRAM_IDS.token, isSigner: false, isWritable: false },
|
{ pubkey: PROGRAM_IDS.token, isSigner: false, isWritable: false },
|
||||||
];
|
];
|
||||||
|
|
|
@ -13,12 +13,11 @@ import * as Layout from '../utils/layout';
|
||||||
/// program account key, governance mint key, council mint key, timelock program account key.
|
/// program account key, governance mint key, council mint key, timelock program account key.
|
||||||
/// 1. `[]` Program account that this config uses
|
/// 1. `[]` Program account that this config uses
|
||||||
/// 2. `[]` Governance mint that this config uses
|
/// 2. `[]` Governance mint that this config uses
|
||||||
/// 3. `[]` Council mint that this config uses [Optional] [Pass in 0s otherwise]
|
/// 3. `[]` Council mint that this config uses [Optional]
|
||||||
export const initTimelockConfigInstruction = (
|
export const initTimelockConfigInstruction = (
|
||||||
timelockConfigAccount: PublicKey,
|
timelockConfigAccount: PublicKey,
|
||||||
programAccount: PublicKey,
|
programAccount: PublicKey,
|
||||||
governanceMint: PublicKey,
|
governanceMint: PublicKey,
|
||||||
councilMint: PublicKey,
|
|
||||||
consensusAlgorithm: number,
|
consensusAlgorithm: number,
|
||||||
executionType: number,
|
executionType: number,
|
||||||
timelockType: number,
|
timelockType: number,
|
||||||
|
@ -26,6 +25,7 @@ export const initTimelockConfigInstruction = (
|
||||||
minimumSlotWaitingPeriod: BN,
|
minimumSlotWaitingPeriod: BN,
|
||||||
timeLimit: BN,
|
timeLimit: BN,
|
||||||
name: string,
|
name: string,
|
||||||
|
councilMint?: PublicKey,
|
||||||
): TransactionInstruction => {
|
): TransactionInstruction => {
|
||||||
const PROGRAM_IDS = utils.programIds();
|
const PROGRAM_IDS = utils.programIds();
|
||||||
|
|
||||||
|
@ -69,8 +69,12 @@ export const initTimelockConfigInstruction = (
|
||||||
{ pubkey: timelockConfigAccount, isSigner: false, isWritable: true },
|
{ pubkey: timelockConfigAccount, isSigner: false, isWritable: true },
|
||||||
{ pubkey: programAccount, isSigner: false, isWritable: false },
|
{ pubkey: programAccount, isSigner: false, isWritable: false },
|
||||||
{ pubkey: governanceMint, isSigner: false, isWritable: false },
|
{ pubkey: governanceMint, isSigner: false, isWritable: false },
|
||||||
{ pubkey: councilMint, isSigner: false, isWritable: false },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (councilMint) {
|
||||||
|
keys.push({ pubkey: councilMint, isSigner: false, isWritable: false });
|
||||||
|
}
|
||||||
|
|
||||||
return new TransactionInstruction({
|
return new TransactionInstruction({
|
||||||
keys,
|
keys,
|
||||||
programId: PROGRAM_IDS.timelock.programId,
|
programId: PROGRAM_IDS.timelock.programId,
|
||||||
|
|
|
@ -10,8 +10,9 @@ export const CONFIG_NAME_LENGTH = 32;
|
||||||
export const INSTRUCTION_LIMIT = 450;
|
export const INSTRUCTION_LIMIT = 450;
|
||||||
export const TRANSACTION_SLOTS = 5;
|
export const TRANSACTION_SLOTS = 5;
|
||||||
export const TEMP_FILE_TXN_SIZE = 1000;
|
export const TEMP_FILE_TXN_SIZE = 1000;
|
||||||
// Key chosen to represent an unused key, a dummy empty. Points to system program.
|
|
||||||
export const ZERO_KEY = '11111111111111111111111111111111';
|
/// Seed for proposal authority
|
||||||
|
export const GOVERNANCE_AUTHORITY_SEED = 'governance';
|
||||||
|
|
||||||
export enum TimelockInstruction {
|
export enum TimelockInstruction {
|
||||||
InitTimelockSet = 1,
|
InitTimelockSet = 1,
|
||||||
|
@ -71,7 +72,7 @@ export interface TimelockConfig {
|
||||||
/// Governance mint
|
/// Governance mint
|
||||||
governanceMint: PublicKey;
|
governanceMint: PublicKey;
|
||||||
/// Council mint (Optional)
|
/// Council mint (Optional)
|
||||||
councilMint: PublicKey;
|
councilMint?: PublicKey;
|
||||||
/// Program ID that is tied to this config (optional)
|
/// Program ID that is tied to this config (optional)
|
||||||
program: PublicKey;
|
program: PublicKey;
|
||||||
/// Time limit in slots for proposal to be open to voting
|
/// Time limit in slots for proposal to be open to voting
|
||||||
|
@ -91,12 +92,13 @@ export const TimelockConfigLayout: typeof BufferLayout.Structure = BufferLayout.
|
||||||
BufferLayout.u8('votingEntryRule'),
|
BufferLayout.u8('votingEntryRule'),
|
||||||
Layout.uint64('minimumSlotWaitingPeriod'),
|
Layout.uint64('minimumSlotWaitingPeriod'),
|
||||||
Layout.publicKey('governanceMint'),
|
Layout.publicKey('governanceMint'),
|
||||||
|
BufferLayout.u8('councilMintOption'),
|
||||||
Layout.publicKey('councilMint'),
|
Layout.publicKey('councilMint'),
|
||||||
Layout.publicKey('program'),
|
Layout.publicKey('program'),
|
||||||
Layout.uint64('timeLimit'),
|
Layout.uint64('timeLimit'),
|
||||||
BufferLayout.seq(BufferLayout.u8(), CONFIG_NAME_LENGTH, 'name'),
|
BufferLayout.seq(BufferLayout.u8(), CONFIG_NAME_LENGTH, 'name'),
|
||||||
BufferLayout.u32('count'),
|
BufferLayout.u32('count'),
|
||||||
BufferLayout.seq(BufferLayout.u8(), 296, 'padding'),
|
BufferLayout.seq(BufferLayout.u8(), 295, 'padding'),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -428,7 +430,7 @@ export const TimelockConfigParser = (
|
||||||
votingEntryRule: data.votingEntryRule,
|
votingEntryRule: data.votingEntryRule,
|
||||||
minimumSlotWaitingPeriod: data.minimumSlotWaitingPeriod,
|
minimumSlotWaitingPeriod: data.minimumSlotWaitingPeriod,
|
||||||
governanceMint: data.governanceMint,
|
governanceMint: data.governanceMint,
|
||||||
councilMint: data.councilMint,
|
councilMint: data.councilMintOption == 1 ? data.councilMint : null,
|
||||||
program: data.program,
|
program: data.program,
|
||||||
timeLimit: data.timeLimit,
|
timeLimit: data.timeLimit,
|
||||||
name: utils.fromUTF8Array(data.name).replaceAll('\u0000', ''),
|
name: utils.fromUTF8Array(data.name).replaceAll('\u0000', ''),
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
PublicKey,
|
PublicKey,
|
||||||
Message,
|
Message,
|
||||||
} from '@solana/web3.js';
|
} from '@solana/web3.js';
|
||||||
import { TimelockSet } from '../models/timelock';
|
import { GOVERNANCE_AUTHORITY_SEED, TimelockSet } from '../models/timelock';
|
||||||
export async function serializeInstruction({
|
export async function serializeInstruction({
|
||||||
connection,
|
connection,
|
||||||
instr,
|
instr,
|
||||||
|
@ -23,7 +23,7 @@ export async function serializeInstruction({
|
||||||
await connection.getRecentBlockhash('max')
|
await connection.getRecentBlockhash('max')
|
||||||
).blockhash;
|
).blockhash;
|
||||||
const [authority] = await PublicKey.findProgramAddress(
|
const [authority] = await PublicKey.findProgramAddress(
|
||||||
[proposal.pubkey.toBuffer()],
|
[Buffer.from(GOVERNANCE_AUTHORITY_SEED), proposal.pubkey.toBuffer()],
|
||||||
PROGRAM_IDS.timelock.programId,
|
PROGRAM_IDS.timelock.programId,
|
||||||
);
|
);
|
||||||
instructionTransaction.setSigners(authority);
|
instructionTransaction.setSigners(authority);
|
||||||
|
|
|
@ -16,7 +16,6 @@ import {
|
||||||
TimelockConfig,
|
TimelockConfig,
|
||||||
TimelockType,
|
TimelockType,
|
||||||
VotingEntryRule,
|
VotingEntryRule,
|
||||||
ZERO_KEY,
|
|
||||||
} from '../../models/timelock';
|
} from '../../models/timelock';
|
||||||
import { PublicKey } from '@solana/web3.js';
|
import { PublicKey } from '@solana/web3.js';
|
||||||
import { Table } from 'antd';
|
import { Table } from 'antd';
|
||||||
|
@ -91,7 +90,7 @@ const columns = [
|
||||||
render: (config: ParsedAccount<TimelockConfig>) => (
|
render: (config: ParsedAccount<TimelockConfig>) => (
|
||||||
<>
|
<>
|
||||||
<MintSourceTokens timelockConfig={config} useGovernance={true} />
|
<MintSourceTokens timelockConfig={config} useGovernance={true} />
|
||||||
{config.info.councilMint.toBase58() != ZERO_KEY && (
|
{config.info.councilMint && (
|
||||||
<MintSourceTokens timelockConfig={config} useGovernance={false} />
|
<MintSourceTokens timelockConfig={config} useGovernance={false} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
ExecutionType,
|
ExecutionType,
|
||||||
TimelockType,
|
TimelockType,
|
||||||
VotingEntryRule,
|
VotingEntryRule,
|
||||||
ZERO_KEY,
|
|
||||||
} from '../../models/timelock';
|
} from '../../models/timelock';
|
||||||
import { LABELS } from '../../constants';
|
import { LABELS } from '../../constants';
|
||||||
import { contexts, utils, tryParseKey } from '@oyster/common';
|
import { contexts, utils, tryParseKey } from '@oyster/common';
|
||||||
|
@ -132,9 +131,8 @@ export function NewForm({
|
||||||
: undefined,
|
: undefined,
|
||||||
councilMint: values.councilMint
|
councilMint: values.councilMint
|
||||||
? new PublicKey(values.councilMint)
|
? new PublicKey(values.councilMint)
|
||||||
: councilVisible
|
: undefined,
|
||||||
? undefined // if visible but empty, set undefined so we instantiate one
|
|
||||||
: new PublicKey(ZERO_KEY), // default empty case, just make it padding since user doesnt want one.
|
|
||||||
program: new PublicKey(values.program),
|
program: new PublicKey(values.program),
|
||||||
name: values.name,
|
name: values.name,
|
||||||
timeLimit: new BN(values.timeLimit),
|
timeLimit: new BN(values.timeLimit),
|
||||||
|
@ -144,6 +142,7 @@ export function NewForm({
|
||||||
connection,
|
connection,
|
||||||
wallet.wallet,
|
wallet.wallet,
|
||||||
uninitializedConfig,
|
uninitializedConfig,
|
||||||
|
councilVisible,
|
||||||
);
|
);
|
||||||
handleOk(newConfig);
|
handleOk(newConfig);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
||||||
import { Button, ButtonProps, Modal, Radio } from 'antd';
|
import { Button, ButtonProps, Modal, Radio } from 'antd';
|
||||||
import { Form, Input, Select } from 'antd';
|
import { Form, Input, Select } from 'antd';
|
||||||
import { Account } from '@solana/web3.js';
|
import { Account } from '@solana/web3.js';
|
||||||
import { DESC_SIZE, NAME_SIZE, ZERO_KEY } from '../../models/timelock';
|
import { DESC_SIZE, NAME_SIZE } from '../../models/timelock';
|
||||||
import { LABELS } from '../../constants';
|
import { LABELS } from '../../constants';
|
||||||
import { contexts, utils } from '@oyster/common';
|
import { contexts, utils } from '@oyster/common';
|
||||||
import { createProposal } from '../../actions/createProposal';
|
import { createProposal } from '../../actions/createProposal';
|
||||||
|
@ -80,7 +80,7 @@ export function NewForm({
|
||||||
|
|
||||||
if (
|
if (
|
||||||
values.proposalMintType === ProposalMintType.Council &&
|
values.proposalMintType === ProposalMintType.Council &&
|
||||||
config.info.councilMint.toBase58() === ZERO_KEY
|
!config.info.councilMint
|
||||||
) {
|
) {
|
||||||
notify({
|
notify({
|
||||||
message: LABELS.THIS_CONFIG_LACKS_COUNCIL,
|
message: LABELS.THIS_CONFIG_LACKS_COUNCIL,
|
||||||
|
|
Loading…
Reference in New Issue