Skip to content

Commit dd46048

Browse files
committed
Update create-spl-multisig to handle undeployed program case
1 parent e5ea47c commit dd46048

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

10411050
if (!fs.existsSync(argv["payer"])) {
@@ -1048,44 +1057,101 @@ yargs(hideBin(process.argv))
10481057
)
10491058
);
10501059

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

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

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

0 commit comments

Comments
 (0)