Skip to content

Commit 5f94da9

Browse files
committed
Update create-spl-multisig to handle undeployed program case
1 parent 4b66309 commit 5f94da9

1 file changed

Lines changed: 112 additions & 46 deletions

File tree

cli/src/index.ts

Lines changed: 112 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,28 +1015,37 @@ yargs(hideBin(process.argv))
10151015
})
10161016
.command("create-spl-multisig <multisigMemberPubkey...>",
10171017
"create a valid SPL Multisig (see https://github.com/wormhole-foundation/native-token-transfers/tree/main/solana#spl-multisig-support for more info)",
1018-
(yargs) =>
1019-
yargs
1020-
.positional("multisigMemberPubkey", {
1021-
describe:
1022-
"public keys of the members that can independently mint",
1023-
type: "string",
1024-
demandOption: true,
1025-
})
1026-
.option("path", options.deploymentPath)
1027-
.option("payer", { ...options.payer, demandOption: true })
1028-
.example(
1029-
"$0 solana create-spl-multisig Sol1234... --payer <SOLANA_KEYPAIR_PATH>",
1030-
"Create multisig with Sol1234... having independent mint privilege alongside NTT token-authority"
1031-
)
1032-
.example(
1033-
"$0 solana create-spl-multisig Sol1234... Sol3456... Sol5678... --payer <SOLANA_KEYPAIR_PATH>",
1034-
"Create multisig with Sol1234..., Sol3456..., and Sol5678... having mint privileges alongside NTT token-authority"
1035-
),
1018+
(yargs) => yargs
1019+
.positional("multisigMemberPubkey", {
1020+
describe: "public keys of the members that can independently mint",
1021+
type: "string",
1022+
demandOption: true,
1023+
})
1024+
.option("manager", {
1025+
describe: "Manager address",
1026+
type: "string",
1027+
})
1028+
.option("token", {
1029+
describe: "Token address",
1030+
type: "string",
1031+
})
1032+
.option("path", options.deploymentPath)
1033+
.option("yes", options.yes)
1034+
.option("payer", { ...options.payer, demandOption: true })
1035+
.example(
1036+
"$0 solana create-spl-multisig Sol1234... --token Sol3456... --manager Sol5678... --payer <SOLANA_KEYPAIR_PATH>",
1037+
"Create multisig with Sol1234... having independent mint privilege alongside NTT token-authority for undeployed program"
1038+
)
1039+
.example(
1040+
"$0 solana create-spl-multisig Sol1234... Sol3456... Sol5678... --payer <SOLANA_KEYPAIR_PATH>",
1041+
"Create multisig with Sol1234..., Sol3456..., and Sol5678... having mint privileges alongside NTT token-authority for deployed program"
1042+
),
10361043
async (argv) => {
10371044
const path = argv["path"];
10381045
const deployments: Config = loadConfig(path);
10391046
const chain: Chain = "Solana";
1047+
const manager = argv["manager"];
1048+
const token = argv["token"];
10401049
const network = deployments.network as Network;
10411050

10421051
if (!fs.existsSync(argv["payer"])) {
@@ -1049,44 +1058,101 @@ yargs(hideBin(process.argv))
10491058
)
10501059
);
10511060

1052-
if (!(chain in deployments.chains)) {
1053-
console.error(`Chain ${chain} not found in ${path}`);
1061+
if (!token !== !manager) {
1062+
console.error(
1063+
"Please provide both --token and --manager for an undeployed program"
1064+
);
10541065
process.exit(1);
10551066
}
1056-
const chainConfig = deployments.chains[chain]!;
1057-
const wh = new Wormhole(network, [solana.Platform, evm.Platform], overrides);
1058-
const ch = wh.getChain(chain);
1059-
const connection = await ch.getRpc();
1060-
const [, , ntt] = await pullChainConfig(
1067+
1068+
const wh = new Wormhole(
10611069
network,
1062-
{ chain, address: toUniversal(chain, chainConfig.manager) },
1070+
[solana.Platform, evm.Platform],
10631071
overrides
10641072
);
1065-
const solanaNtt = ntt as SolanaNtt<typeof network, SolanaChains>;
1066-
const tokenAuthority = NTT.pdas(chainConfig.manager).tokenAuthority();
1073+
const ch = wh.getChain(chain);
1074+
const connection: Connection = await ch.getRpc();
1075+
1076+
let solanaNtt: SolanaNtt<typeof network, SolanaChains> | undefined;
1077+
let managerKey: PublicKey;
1078+
let major: number;
1079+
let tokenProgram: PublicKey;
1080+
1081+
// program deployed so fetch token and manager addresses from deployment
1082+
if (!token && !manager) {
1083+
if (!(chain in deployments.chains)) {
1084+
console.error(`Either provide --token and --manager flags, or ensure ${path} contains a valid ${chain} configuration`);
1085+
process.exit(1);
1086+
}
1087+
const chainConfig = deployments.chains[chain]!;
1088+
const [, , ntt] = await pullChainConfig(
1089+
network,
1090+
{ chain, address: toUniversal(chain, chainConfig.manager) },
1091+
overrides
1092+
);
1093+
solanaNtt = ntt as SolanaNtt<typeof network, SolanaChains>;
1094+
managerKey = new PublicKey(chainConfig.manager);
1095+
major = Number(solanaNtt.version.split(".")[0]);
1096+
tokenProgram = (await solanaNtt.getConfig()).tokenProgram;
1097+
}
1098+
// default values as undeployed program
1099+
else {
1100+
// ensure mint is valid
1101+
const tokenMint = new PublicKey(token!);
1102+
const mintInfo = await connection.getAccountInfo(tokenMint);
1103+
if (!mintInfo) {
1104+
console.error(
1105+
`Mint ${token} not found on ${ch.chain} ${ch.network}`
1106+
);
1107+
process.exit(1);
1108+
}
1109+
spl.unpackMint(tokenMint, mintInfo, mintInfo.owner);
1110+
1111+
solanaNtt = undefined;
1112+
managerKey = new PublicKey(manager!);
1113+
major = -1;
1114+
tokenProgram = mintInfo.owner;
1115+
}
1116+
1117+
const tokenAuthority = NTT.pdas(managerKey).tokenAuthority();
10671118

10681119
// check if SPL-Multisig is supported for manager version
1069-
const major = Number(solanaNtt.version.split(".")[0]);
1070-
if (major < 3) {
1120+
// undeployed -- assume version compatible via warning
1121+
if (major === -1 && !argv["yes"]) {
1122+
console.warn(
1123+
chalk.yellow(
1124+
"SPL Multisig token mint authority is only supported for versions >= 3.x.x"
1125+
)
1126+
);
1127+
console.warn(
1128+
chalk.yellow(
1129+
"Ensure the program version you wish to deploy supports SPL Multisig token mint authority"
1130+
)
1131+
);
1132+
await askForConfirmation();
1133+
}
1134+
// unsupported version
1135+
else if (major < 3) {
10711136
console.error(
10721137
"SPL Multisig token mint authority is only supported for versions >= 3.x.x"
10731138
);
1074-
console.error("Use 'ntt upgrade' to upgrade the NTT contract to a specific version.");
1139+
console.error(
1140+
"Use 'ntt upgrade' to upgrade the NTT contract to a specific version."
1141+
);
10751142
process.exit(1);
10761143
}
10771144

10781145
try {
10791146
// use same tokenProgram as token to create multisig
1080-
const tokenProgram = (await solanaNtt.getConfig()).tokenProgram;
10811147
const additionalMemberPubkeys = (argv["multisigMemberPubkey"] as any).map(
10821148
(key: string) => new PublicKey(key)
10831149
);
10841150
const multisig = await spl.createMultisig(
10851151
connection,
10861152
payerKeypair,
10871153
[
1088-
tokenAuthority,
1089-
...additionalMemberPubkeys,
1154+
tokenAuthority,
1155+
...additionalMemberPubkeys,
10901156
],
10911157
1,
10921158
undefined,
@@ -1326,18 +1392,18 @@ yargs(hideBin(process.argv))
13261392
try {
13271393
const latestBlockHash = await connection.getLatestBlockhash();
13281394
const messageV0 = new TransactionMessage({
1329-
payerKey: payerKeypair.publicKey,
1330-
instructions: [
1331-
await NTT.createAcceptTokenAuthorityInstruction(
1332-
solanaNtt.program,
1333-
await solanaNtt.getConfig(),
1334-
{
1335-
currentAuthority: payerKeypair.publicKey,
1336-
multisigTokenAuthority,
1337-
}
1338-
),
1339-
],
1340-
recentBlockhash: latestBlockHash.blockhash,
1395+
payerKey: payerKeypair.publicKey,
1396+
instructions: [
1397+
await NTT.createAcceptTokenAuthorityInstruction(
1398+
solanaNtt.program,
1399+
await solanaNtt.getConfig(),
1400+
{
1401+
currentAuthority: payerKeypair.publicKey,
1402+
multisigTokenAuthority,
1403+
}
1404+
),
1405+
],
1406+
recentBlockhash: latestBlockHash.blockhash,
13411407
}).compileToV0Message(luts);
13421408
const vtx = new VersionedTransaction(messageV0);
13431409
vtx.sign([payerKeypair]);

0 commit comments

Comments
 (0)