Skip to content

Commit f74f592

Browse files
committed
Checkpoint
1 parent d22938b commit f74f592

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./propose";
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import Squads, { getIxAuthorityPDA, getTxPDA } from "@sqds/mesh";
2+
import {
3+
PACKET_DATA_SIZE,
4+
PublicKey,
5+
Transaction,
6+
TransactionInstruction,
7+
} from "@solana/web3.js";
8+
import { BN } from "bn.js";
9+
import { AnchorProvider } from "@project-serum/anchor";
10+
import {
11+
createWormholeProgramInterface,
12+
getPostMessageAccounts,
13+
} from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole";
14+
import { encodeExecutePostedVaa } from "../governance_payload/ExecutePostedVaa";
15+
16+
type SquadInstruction = {
17+
instruction: TransactionInstruction;
18+
authorityIndex?: number;
19+
authorityBump?: number;
20+
authorityType?: string;
21+
};
22+
23+
export async function proposeInstructions(
24+
squad: Squads,
25+
vault: PublicKey,
26+
chain: "solana",
27+
instructions: TransactionInstruction[],
28+
wormholeAddress?: PublicKey
29+
): Promise<PublicKey> {
30+
const msAccount = await squad.getMultisig(vault);
31+
let txToSend: Transaction[] = [];
32+
33+
const createProposal = new Transaction().add(
34+
await squad.buildCreateTransaction(
35+
msAccount.publicKey,
36+
msAccount.authorityIndex,
37+
msAccount.transactionIndex + 1
38+
)
39+
);
40+
const newProposalAddress = getTxPDA(
41+
vault,
42+
new BN(msAccount.transactionIndex + 1),
43+
squad.multisigProgramId
44+
)[0];
45+
txToSend.push(createProposal);
46+
47+
if (chain == "solana") {
48+
for (let i = 0; i < instructions.length; i++) {
49+
txToSend.push(
50+
new Transaction().add(
51+
await squad.buildAddInstruction(
52+
vault,
53+
newProposalAddress,
54+
instructions[i],
55+
i
56+
)
57+
)
58+
);
59+
}
60+
} else {
61+
if (!wormholeAddress) {
62+
throw new Error("Need wormhole address");
63+
}
64+
for (let i = 0; i < instructions.length; i++) {
65+
const squadIx = await wrapAsRemoteInstruction(
66+
squad,
67+
vault,
68+
newProposalAddress,
69+
instructions[i],
70+
i,
71+
wormholeAddress
72+
);
73+
txToSend.push(
74+
new Transaction().add(
75+
await squad.buildAddInstruction(
76+
vault,
77+
newProposalAddress,
78+
squadIx.instruction,
79+
i,
80+
squadIx.authorityIndex,
81+
squadIx.authorityBump,
82+
squadIx.authorityType
83+
)
84+
)
85+
);
86+
}
87+
}
88+
89+
txToSend.push(
90+
new Transaction().add(
91+
await squad.buildActivateTransaction(vault, newProposalAddress)
92+
)
93+
);
94+
txToSend.push(
95+
new Transaction().add(
96+
await squad.buildApproveTransaction(vault, newProposalAddress)
97+
)
98+
);
99+
100+
await new AnchorProvider(
101+
squad.connection,
102+
squad.wallet,
103+
AnchorProvider.defaultOptions()
104+
).sendAll(
105+
txToSend.map((tx) => {
106+
return { tx, signers: [] };
107+
})
108+
);
109+
return newProposalAddress;
110+
}
111+
112+
export async function wrapAsRemoteInstruction(
113+
squad: Squads,
114+
vault: PublicKey,
115+
proposalAddress: PublicKey,
116+
instruction: TransactionInstruction,
117+
instructionIndex: number,
118+
wormholeAddress: PublicKey
119+
): Promise<SquadInstruction> {
120+
const [messagePDA, messagePdaBump] = getIxAuthorityPDA(
121+
proposalAddress,
122+
new BN(instructionIndex),
123+
squad.multisigProgramId
124+
);
125+
126+
const emitter = squad.getAuthorityPDA(vault, 0);
127+
128+
const provider = new AnchorProvider(
129+
squad.connection,
130+
squad.wallet,
131+
AnchorProvider.defaultOptions()
132+
);
133+
const wormholeProgram = createWormholeProgramInterface(
134+
wormholeAddress,
135+
provider
136+
);
137+
const buffer = Buffer.alloc(PACKET_DATA_SIZE);
138+
const span = encodeExecutePostedVaa(
139+
{
140+
header: { action: "ExecutePostedVaa", targetChainId: "pythnet" },
141+
instructions: [instruction],
142+
},
143+
buffer
144+
);
145+
146+
const accounts = getPostMessageAccounts(
147+
wormholeAddress,
148+
emitter,
149+
emitter,
150+
messagePDA
151+
);
152+
return {
153+
instruction: await wormholeProgram.methods
154+
.postMessage(0, buffer.subarray(0, span), 0)
155+
.accounts(accounts)
156+
.instruction(),
157+
authorityIndex: instructionIndex,
158+
authorityBump: messagePdaBump,
159+
authorityType: "custom",
160+
};
161+
}

0 commit comments

Comments
 (0)