Run prettier (#318)

Co-authored-by: Jayant Krishnamurthy <jkrishnamurthy@jumptrading.com>
This commit is contained in:
Jayant Krishnamurthy 2022-09-29 13:22:14 -07:00 committed by GitHub
parent 863a983a1a
commit 89cc35d3a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 133 additions and 69 deletions

View File

@ -11,7 +11,8 @@ import {
Keypair, Keypair,
LAMPORTS_PER_SOL, LAMPORTS_PER_SOL,
PublicKey, PublicKey,
SystemProgram, TransactionInstruction, SystemProgram,
TransactionInstruction,
} from "@solana/web3.js"; } from "@solana/web3.js";
import Squads from "@sqds/mesh"; import Squads from "@sqds/mesh";
import bs58 from "bs58"; import bs58 from "bs58";
@ -47,7 +48,13 @@ program
) )
.option("-p, --payload <hex-string>", "payload to sign", "0xdeadbeef") .option("-p, --payload <hex-string>", "payload to sign", "0xdeadbeef")
.action(async (options) => { .action(async (options) => {
const squad = await getSquadsClient(options.cluster, options.ledger, options.ledgerDerivationAccount, options.ledgerDerivationChange, options.wallet); const squad = await getSquadsClient(
options.cluster,
options.ledger,
options.ledgerDerivationAccount,
options.ledgerDerivationChange,
options.wallet
);
await createWormholeMsgMultisigTx( await createWormholeMsgMultisigTx(
options.cluster, options.cluster,
squad, squad,
@ -59,7 +66,9 @@ program
program program
.command("set-is-active") .command("set-is-active")
.description("Create a new multisig transaction to set the attester is-active flag") .description(
"Create a new multisig transaction to set the attester is-active flag"
)
.option("-c, --cluster <network>", "solana cluster to use", "devnet") .option("-c, --cluster <network>", "solana cluster to use", "devnet")
.requiredOption("-v, --vault-address <address>", "multisig vault address") .requiredOption("-v, --vault-address <address>", "multisig vault address")
.option("-l, --ledger", "use ledger") .option("-l, --ledger", "use ledger")
@ -77,17 +86,38 @@ program
"keys/key.json" "keys/key.json"
) )
.option("-a, --attester <program id>") .option("-a, --attester <program id>")
.option("-i, --is-active <true/false>", "set the isActive field to this value", true) .option(
"-i, --is-active <true/false>",
"set the isActive field to this value",
true
)
.action(async (options) => { .action(async (options) => {
const squad = await getSquadsClient(options.cluster, options.ledger, options.ledgerDerivationAccount, options.ledgerDerivationChange, options.wallet); const squad = await getSquadsClient(
options.cluster,
options.ledger,
options.ledgerDerivationAccount,
options.ledgerDerivationChange,
options.wallet
);
const msAccount = await squad.getMultisig(options.vaultAddress); const msAccount = await squad.getMultisig(options.vaultAddress);
const vaultAuthority = squad.getAuthorityPDA( const vaultAuthority = squad.getAuthorityPDA(
msAccount.publicKey, msAccount.publicKey,
msAccount.authorityIndex msAccount.authorityIndex
); );
const attesterProgramId = new PublicKey(options.attester); const attesterProgramId = new PublicKey(options.attester);
const txKey = await createTx(squad, options.ledger, new PublicKey(options.vaultAddress)); const txKey = await createTx(
const instructions = [await setIsActiveIx(vaultAuthority, vaultAuthority, attesterProgramId, options.active)]; squad,
options.ledger,
new PublicKey(options.vaultAddress)
);
const instructions = [
await setIsActiveIx(
vaultAuthority,
vaultAuthority,
attesterProgramId,
options.active
),
];
await addInstructionsToTx(squad, options.ledger, txKey, instructions); await addInstructionsToTx(squad, options.ledger, txKey, instructions);
}); });
@ -146,11 +176,12 @@ const solanaClusterMappingToWormholeNetwork: Record<Cluster, WormholeNetwork> =
"mainnet-beta": "MAINNET", "mainnet-beta": "MAINNET",
}; };
async function getSquadsClient(cluster: Cluster, async function getSquadsClient(
ledger: boolean, cluster: Cluster,
ledgerDerivationAccount: number | undefined, ledger: boolean,
ledgerDerivationChange: number | undefined, ledgerDerivationAccount: number | undefined,
walletPath: string, ledgerDerivationChange: number | undefined,
walletPath: string
) { ) {
let wallet: LedgerNodeWallet | NodeWallet; let wallet: LedgerNodeWallet | NodeWallet;
if (ledger) { if (ledger) {
@ -176,7 +207,7 @@ async function getSquadsClient(cluster: Cluster,
async function createTx( async function createTx(
squad: Squads, squad: Squads,
ledger: boolean, ledger: boolean,
vault: PublicKey, vault: PublicKey
): Promise<PublicKey> { ): Promise<PublicKey> {
const msAccount = await squad.getMultisig(vault); const msAccount = await squad.getMultisig(vault);
@ -201,7 +232,9 @@ async function addInstructionsToTx(
instructions: TransactionInstruction[] instructions: TransactionInstruction[]
) { ) {
for (let i = 0; i < instructions.length; i++) { for (let i = 0; i < instructions.length; i++) {
console.log(`Adding instruction ${i}/${instructions.length} to transaction...`); console.log(
`Adding instruction ${i}/${instructions.length} to transaction...`
);
if (ledger) { if (ledger) {
console.log("Please approve the transaction on your ledger device..."); console.log("Please approve the transaction on your ledger device...");
} }
@ -221,33 +254,36 @@ async function setIsActiveIx(
attesterProgramId: PublicKey, attesterProgramId: PublicKey,
isActive: boolean isActive: boolean
): Promise<TransactionInstruction> { ): Promise<TransactionInstruction> {
const configKey = PublicKey.createProgramAddressSync([Buffer.from("pyth2wormhole-config-v3")], attesterProgramId) const configKey = PublicKey.createProgramAddressSync(
[Buffer.from("pyth2wormhole-config-v3")],
attesterProgramId
);
const config: AccountMeta = { const config: AccountMeta = {
pubkey: configKey, pubkey: configKey,
isSigner: false, isSigner: false,
isWritable: true, isWritable: true,
} };
const opsOwner: AccountMeta = { const opsOwner: AccountMeta = {
pubkey: opsOwnerKey, pubkey: opsOwnerKey,
isSigner: true, isSigner: true,
isWritable: true, isWritable: true,
} };
const payer: AccountMeta = { const payer: AccountMeta = {
pubkey: payerKey, pubkey: payerKey,
isSigner: true, isSigner: true,
isWritable: true, isWritable: true,
} };
const isActiveInt = (isActive === true) ? 1 : 0; const isActiveInt = isActive === true ? 1 : 0;
// first byte is the isActive instruction, second byte is true/false // first byte is the isActive instruction, second byte is true/false
const data = new Buffer([4, isActiveInt]) const data = new Buffer([4, isActiveInt]);
return { return {
keys: [config, opsOwner, payer], keys: [config, opsOwner, payer],
programId: attesterProgramId, programId: attesterProgramId,
data: data, data: data,
} };
} }
async function getWormholeMessageIx( async function getWormholeMessageIx(
@ -286,7 +322,7 @@ async function getWormholeMessageIx(
emitter.toBase58(), emitter.toBase58(),
message.toBase58(), message.toBase58(),
0, 0,
Uint8Array.from(Buffer.from(payload, 'hex')), Uint8Array.from(Buffer.from(payload, "hex")),
"CONFIRMED" "CONFIRMED"
) )
), ),
@ -312,9 +348,12 @@ async function createWormholeMsgMultisigTx(
const message = Keypair.generate(); const message = Keypair.generate();
fs.mkdirSync('keys', {recursive: true}); fs.mkdirSync("keys", { recursive: true });
// save message to Uint8 array keypair file called mesage.json // save message to Uint8 array keypair file called mesage.json
fs.writeFileSync(`keys/message-${txKey.toBase58()}.json`, `[${message.secretKey.toString()}]`); fs.writeFileSync(
`keys/message-${txKey.toBase58()}.json`,
`[${message.secretKey.toString()}]`
);
console.log(`Message Address: ${message.publicKey.toBase58()}`); console.log(`Message Address: ${message.publicKey.toBase58()}`);
console.log("Creating wormhole instructions..."); console.log("Creating wormhole instructions...");
@ -431,7 +470,6 @@ async function executeMultisigTx(
); );
await new Promise((resolve) => setTimeout(resolve, 10000)); await new Promise((resolve) => setTimeout(resolve, 10000));
const txDetails = await squad.connection.getParsedTransaction( const txDetails = await squad.connection.getParsedTransaction(
signature, signature,
"confirmed" "confirmed"
@ -460,10 +498,10 @@ async function executeMultisigTx(
const { vaaBytes } = await response.json(); const { vaaBytes } = await response.json();
console.log(`VAA (Base64): ${vaaBytes}`); console.log(`VAA (Base64): ${vaaBytes}`);
const parsedVaa = await parse(vaaBytes); const parsedVaa = await parse(vaaBytes);
console.log(`VAA (Hex): ${Buffer.from(vaaBytes).toString('hex')}`) console.log(`VAA (Hex): ${Buffer.from(vaaBytes).toString("hex")}`);
console.log(`Emitter chain: ${parsedVaa.emitter_chain}`); console.log(`Emitter chain: ${parsedVaa.emitter_chain}`);
console.log(`Nonce: ${parsedVaa.nonce}`); console.log(`Nonce: ${parsedVaa.nonce}`);
console.log(`Payload: ${Buffer.from(parsedVaa.payload).toString('hex')}`); console.log(`Payload: ${Buffer.from(parsedVaa.payload).toString("hex")}`);
} }
async function parse(data: string) { async function parse(data: string) {

View File

@ -1,30 +1,30 @@
import type { default as Transport } from '@ledgerhq/hw-transport'; import type { default as Transport } from "@ledgerhq/hw-transport";
import { StatusCodes, TransportStatusError } from '@ledgerhq/hw-transport'; import { StatusCodes, TransportStatusError } from "@ledgerhq/hw-transport";
import type { Transaction } from '@solana/web3.js'; import type { Transaction } from "@solana/web3.js";
import { PublicKey } from '@solana/web3.js'; import { PublicKey } from "@solana/web3.js";
export function getDerivationPath(account?: number, change?: number): Buffer { export function getDerivationPath(account?: number, change?: number): Buffer {
const length = account !== undefined ? (change === undefined ? 3 : 4) : 2; const length = account !== undefined ? (change === undefined ? 3 : 4) : 2;
const derivationPath = Buffer.alloc(1 + length * 4); const derivationPath = Buffer.alloc(1 + length * 4);
let offset = derivationPath.writeUInt8(length, 0); let offset = derivationPath.writeUInt8(length, 0);
offset = derivationPath.writeUInt32BE(harden(44), offset); // Using BIP44 offset = derivationPath.writeUInt32BE(harden(44), offset); // Using BIP44
offset = derivationPath.writeUInt32BE(harden(501), offset); // Solana's BIP44 path offset = derivationPath.writeUInt32BE(harden(501), offset); // Solana's BIP44 path
if (account !== undefined) { if (account !== undefined) {
offset = derivationPath.writeUInt32BE(harden(account), offset); offset = derivationPath.writeUInt32BE(harden(account), offset);
if (change !== undefined) { if (change !== undefined) {
derivationPath.writeUInt32BE(harden(change), offset); derivationPath.writeUInt32BE(harden(change), offset);
}
} }
}
return derivationPath; return derivationPath;
} }
const BIP32_HARDENED_BIT = (1 << 31) >>> 0; const BIP32_HARDENED_BIT = (1 << 31) >>> 0;
function harden(n: number): number { function harden(n: number): number {
return (n | BIP32_HARDENED_BIT) >>> 0; return (n | BIP32_HARDENED_BIT) >>> 0;
} }
const INS_GET_PUBKEY = 0x05; const INS_GET_PUBKEY = 0x05;
@ -41,44 +41,70 @@ const MAX_PAYLOAD = 255;
const LEDGER_CLA = 0xe0; const LEDGER_CLA = 0xe0;
/** @internal */ /** @internal */
export async function getPublicKey(transport: Transport, derivationPath: Buffer): Promise<PublicKey> { export async function getPublicKey(
const bytes = await send(transport, INS_GET_PUBKEY, P1_NON_CONFIRM, derivationPath); transport: Transport,
return new PublicKey(bytes); derivationPath: Buffer
): Promise<PublicKey> {
const bytes = await send(
transport,
INS_GET_PUBKEY,
P1_NON_CONFIRM,
derivationPath
);
return new PublicKey(bytes);
} }
/** @internal */ /** @internal */
export async function signTransaction( export async function signTransaction(
transport: Transport, transport: Transport,
transaction: Transaction, transaction: Transaction,
derivationPath: Buffer derivationPath: Buffer
): Promise<Buffer> { ): Promise<Buffer> {
const paths = Buffer.alloc(1); const paths = Buffer.alloc(1);
paths.writeUInt8(1, 0); paths.writeUInt8(1, 0);
const message = transaction.serializeMessage(); const message = transaction.serializeMessage();
const data = Buffer.concat([paths, derivationPath, message]); const data = Buffer.concat([paths, derivationPath, message]);
return await send(transport, INS_SIGN_MESSAGE, P1_CONFIRM, data); return await send(transport, INS_SIGN_MESSAGE, P1_CONFIRM, data);
} }
async function send(transport: Transport, instruction: number, p1: number, data: Buffer): Promise<Buffer> { async function send(
let p2 = 0; transport: Transport,
let offset = 0; instruction: number,
p1: number,
data: Buffer
): Promise<Buffer> {
let p2 = 0;
let offset = 0;
if (data.length > MAX_PAYLOAD) { if (data.length > MAX_PAYLOAD) {
while (data.length - offset > MAX_PAYLOAD) { while (data.length - offset > MAX_PAYLOAD) {
const buffer = data.subarray(offset, offset + MAX_PAYLOAD); const buffer = data.subarray(offset, offset + MAX_PAYLOAD);
const response = await transport.send(LEDGER_CLA, instruction, p1, p2 | P2_MORE, buffer); const response = await transport.send(
// @ts-ignore -- TransportStatusError is a constructor Function, not a Class LEDGER_CLA,
if (response.length !== 2) throw new TransportStatusError(StatusCodes.INCORRECT_DATA); instruction,
p1,
p2 | P2_MORE,
buffer
);
// @ts-ignore -- TransportStatusError is a constructor Function, not a Class
if (response.length !== 2)
throw new TransportStatusError(StatusCodes.INCORRECT_DATA);
p2 |= P2_EXTEND; p2 |= P2_EXTEND;
offset += MAX_PAYLOAD; offset += MAX_PAYLOAD;
}
} }
}
const buffer = data.subarray(offset); const buffer = data.subarray(offset);
const response = await transport.send(LEDGER_CLA, instruction, p1, p2, buffer); const response = await transport.send(
LEDGER_CLA,
instruction,
p1,
p2,
buffer
);
return response.subarray(0, response.length - 2); return response.subarray(0, response.length - 2);
} }