Xc admin/add executor (#466)

* Add encoder

* Update test

* Cleanup

* More cleanup

* Add executor

* Update comment

* Update package lock

* Cleanup

* Fix bug and error handling
This commit is contained in:
guibescos 2023-01-10 14:02:14 -06:00 committed by GitHub
parent 1153abe6ff
commit 80fe230563
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1809 additions and 4838 deletions

View File

@ -5,6 +5,7 @@ repos:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
exclude: package-lock.json
# Hook to format many type of files in the repo
# including solidity contracts.
- repo: https://github.com/pre-commit/mirrors-prettier

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
{
"name": "crank-executor",
"version": "0.0.0",
"description": "A crank to executed all executeReady multisig transaction",
"author": "",
"homepage": "https://github.com/pyth-network/pyth-crosschain",
"license": "ISC",
"main": "src/index.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/pyth-network/pyth-crosschain.git"
},
"bugs": {
"url": "https://github.com/pyth-network/pyth-crosschain/issues"
},
"scripts": {
"build": "tsc",
"format": "prettier --write \"src/**/*.ts\""
},
"dependencies": {
"@coral-xyz/anchor": "^0.26.0",
"@pythnetwork/client": "^2.9.0",
"@solana/web3.js": "^1.73.0",
"@sqds/mesh": "^1.0.6",
"ts-node": "^10.9.1"
}
}

View File

@ -0,0 +1,80 @@
import {
Commitment,
Connection,
Keypair,
PublicKey,
SendTransactionError,
Transaction,
} from "@solana/web3.js";
import SquadsMesh, { DEFAULT_MULTISIG_PROGRAM_ID, getIxPDA } from "@sqds/mesh";
import * as fs from "fs";
import NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet";
import { getProposals } from "xc-admin-common";
import BN from "bn.js";
import { AnchorProvider } from "@project-serum/anchor";
import {
getPythClusterApiUrl,
PythCluster,
} from "@pythnetwork/client/lib/cluster";
export function envOrErr(env: string): string {
const val = process.env[env];
if (!val) {
throw new Error(`environment variable "${env}" must be set`);
}
return String(process.env[env]);
}
const CLUSTER: string = envOrErr("CLUSTER");
const COMMITMENT: Commitment =
(process.env.COMMITMENT as Commitment) ?? "confirmed";
const VAULT: PublicKey = new PublicKey(envOrErr("VAULT"));
const KEYPAIR: Keypair = Keypair.fromSecretKey(
Uint8Array.from(JSON.parse(fs.readFileSync(envOrErr("WALLET"), "ascii")))
);
async function run() {
const squad = new SquadsMesh({
connection: new Connection(
getPythClusterApiUrl(CLUSTER as PythCluster),
COMMITMENT
),
wallet: new NodeWallet(KEYPAIR),
multisigProgramId: DEFAULT_MULTISIG_PROGRAM_ID,
});
const proposals = await getProposals(squad, VAULT, undefined, "executeReady");
for (const proposal of proposals) {
// If we have previously cancelled because the proposal was failing, don't attempt
if (proposal.cancelled.length == 0) {
for (
let i = proposal.executedIndex + 1;
i <= proposal.instructionIndex;
i++
) {
const transaction = new Transaction().add(
await squad.buildExecuteInstruction(
proposal.publicKey,
getIxPDA(proposal.publicKey, new BN(i), squad.multisigProgramId)[0]
)
);
try {
await new AnchorProvider(squad.connection, squad.wallet, {
commitment: COMMITMENT,
preflightCommitment: COMMITMENT,
}).sendAndConfirm(transaction, []);
} catch (error) {
// Mark the transaction as cancelled if we failed to run it
if (error instanceof SendTransactionError) {
await squad.cancelTransaction(proposal.publicKey);
}
break;
}
}
}
}
}
(async () => {
await run();
})();

View File

@ -0,0 +1,16 @@
{
"compilerOptions": {
"declaration": true,
"target": "es2016",
"module": "commonjs",
"outDir": "lib",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"noErrorTruncation": true
},
"include": ["src/**/*.ts"],
"exclude": ["src/__tests__/"]
}

View File

@ -9,16 +9,18 @@ import BN from "bn.js";
import lodash from "lodash";
/**
* Find all active proposals for vault `vault` using Squads client `squad`
* Find all proposals for vault `vault` using Squads client `squad`
* @param squad Squads client
* @param vault vault public key. It needs to exist in the instance of squads that `squad` is targeting
* @param offset (optional) ignore all proposals with `proposal_index < offset`
* @param state filter by status
* @returns All the proposal accounts as `TransactionAccount`
*/
export async function getActiveProposals(
export async function getProposals(
squad: Squads,
vault: PublicKey,
offset: number = 1
offset: number = 1,
state: "active" | "executeReady" | "executed" | "all" = "all"
): Promise<TransactionAccount[]> {
const msAccount = await squad.getMultisig(vault);
let txKeys = lodash
@ -29,7 +31,9 @@ export async function getActiveProposals(
.filter(
(x: TransactionAccount | null): x is TransactionAccount => x != null
)
.filter((x) => lodash.isEqual(x.status, { active: {} }));
.filter((x) =>
state === "all" ? true : lodash.isEqual(x.status, { [state]: {} })
);
}
/**