Skip to content

Commit e986b69

Browse files
authored
feat(solana): js sdk (#1307)
* Do it * Remove some duplicate code * Cleanup * Cleanup * Cleanup import * Correct description * Fix path * Cleanup deps * Unique * Works * Continue * Lint * Lint config * Fix ci * Checkpoint * Checkpoint * Gitignore * Cleanup * Cleanup * Continue building the sdk * build function * Remove files * Remove files * Rename * Refactor : make transaction builder * Make commitment * Move * Progress * Checkpoint * Ephemeral signers 2 * Checkpoint * Checkpoint * Fix bug * Cleanup idls * Compute units * Make program addresses configurable * Handle arrays * Handle arrays * Move PythSolanaReceiver * Cleanup constants * Contants * Refactor constants * Gitignore refactor * package lock * Cleanup idl * Add useful static * Add useful static * Add useful static * Lint * Add lint config
1 parent 3835042 commit e986b69

File tree

28 files changed

+5682
-396
lines changed

28 files changed

+5682
-396
lines changed

.github/workflows/ci-solana-contract.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ jobs:
3232
- name: Run tests
3333
run: cargo-test-sbf
3434
- name: Run sdk tests
35-
run: cargo test --p pyth-solana-sdk
35+
run: cargo test --package pyth-solana-receiver-state

governance/xc_admin/packages/xc_admin_common/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
"bigint-buffer": "^1.1.5",
3030
"ethers": "^5.7.2",
3131
"lodash": "^4.17.21",
32-
"typescript": "^4.9.4"
32+
"typescript": "^4.9.4",
33+
"@pythnetwork/solana-utils": "*"
3334
},
3435
"devDependencies": {
3536
"@types/bn.js": "^5.1.1",

governance/xc_admin/packages/xc_admin_common/src/__tests__/TransactionSize.test.ts

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,13 @@ import {
1515
} from "@solana/web3.js";
1616
import {
1717
batchIntoExecutorPayload,
18-
batchIntoTransactions,
19-
getSizeOfCompressedU16,
2018
getSizeOfExecutorInstructions,
21-
getSizeOfTransaction,
2219
MAX_EXECUTOR_PAYLOAD_SIZE,
2320
} from "..";
24-
25-
it("Unit test compressed u16 size", async () => {
26-
expect(getSizeOfCompressedU16(127)).toBe(1);
27-
expect(getSizeOfCompressedU16(128)).toBe(2);
28-
expect(getSizeOfCompressedU16(16383)).toBe(2);
29-
expect(getSizeOfCompressedU16(16384)).toBe(3);
30-
});
21+
import {
22+
getSizeOfTransaction,
23+
TransactionBuilder,
24+
} from "@pythnetwork/solana-utils";
3125

3226
it("Unit test for getSizeOfTransaction", async () => {
3327
jest.setTimeout(60000);
@@ -84,7 +78,7 @@ it("Unit test for getSizeOfTransaction", async () => {
8478
transaction.recentBlockhash = "GqdFtdM7zzWw33YyHtBNwPhyBsdYKcfm9gT47bWnbHvs"; // Mock blockhash from devnet
8579
transaction.feePayer = payer.publicKey;
8680
expect(transaction.serialize({ requireAllSignatures: false }).length).toBe(
87-
getSizeOfTransaction(ixsToSend)
81+
getSizeOfTransaction(ixsToSend, false)
8882
);
8983
});
9084

@@ -115,21 +109,22 @@ it("Unit test for getSizeOfTransaction", async () => {
115109
);
116110
}
117111

118-
const txToSend: Transaction[] = batchIntoTransactions(ixsToSend);
112+
const txToSend: Transaction[] =
113+
TransactionBuilder.batchIntoLegacyTransactions(ixsToSend);
119114
expect(
120115
txToSend.map((tx) => tx.instructions.length).reduce((a, b) => a + b)
121116
).toBe(ixsToSend.length);
122117
expect(
123118
txToSend.every(
124-
(tx) => getSizeOfTransaction(tx.instructions) <= PACKET_DATA_SIZE
119+
(tx) => getSizeOfTransaction(tx.instructions, false) <= PACKET_DATA_SIZE
125120
)
126121
).toBeTruthy();
127122

128123
for (let tx of txToSend) {
129124
tx.recentBlockhash = "GqdFtdM7zzWw33YyHtBNwPhyBsdYKcfm9gT47bWnbHvs"; // Mock blockhash from devnet
130125
tx.feePayer = payer.publicKey;
131126
expect(tx.serialize({ requireAllSignatures: false }).length).toBe(
132-
getSizeOfTransaction(tx.instructions)
127+
getSizeOfTransaction(tx.instructions, false)
133128
);
134129
}
135130

governance/xc_admin/packages/xc_admin_common/src/propose.ts

Lines changed: 3 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import SquadsMesh, { getIxAuthorityPDA, getTxPDA } from "@sqds/mesh";
2525
import { MultisigAccount } from "@sqds/mesh/lib/types";
2626
import { mapKey } from "./remote_executor";
2727
import { WORMHOLE_ADDRESS } from "./wormhole";
28+
import { TransactionBuilder } from "@pythnetwork/solana-utils";
2829

2930
export const MAX_EXECUTOR_PAYLOAD_SIZE = PACKET_DATA_SIZE - 687; // Bigger payloads won't fit in one addInstruction call when adding to the proposal
3031
export const MAX_INSTRUCTIONS_PER_PROPOSAL = 256 - 1;
@@ -256,7 +257,7 @@ export class MultisigVault {
256257
ixToSend.push(await this.activateProposalIx(proposalAddress));
257258
ixToSend.push(await this.approveProposalIx(proposalAddress));
258259

259-
const txToSend = batchIntoTransactions(ixToSend);
260+
const txToSend = TransactionBuilder.batchIntoLegacyTransactions(ixToSend);
260261
await this.sendAllTransactions(txToSend);
261262
return proposalAddress;
262263
}
@@ -360,7 +361,7 @@ export class MultisigVault {
360361
}
361362
}
362363

363-
const txToSend = batchIntoTransactions(ixToSend);
364+
const txToSend = TransactionBuilder.batchIntoLegacyTransactions(ixToSend);
364365

365366
await this.sendAllTransactions(txToSend);
366367
return newProposals;
@@ -445,32 +446,6 @@ export function batchIntoExecutorPayload(
445446
return batches;
446447
}
447448

448-
/**
449-
* Batch instructions into transactions
450-
*/
451-
export function batchIntoTransactions(
452-
instructions: TransactionInstruction[]
453-
): Transaction[] {
454-
let i = 0;
455-
const txToSend: Transaction[] = [];
456-
while (i < instructions.length) {
457-
let j = i + 2;
458-
while (
459-
j < instructions.length &&
460-
getSizeOfTransaction(instructions.slice(i, j)) <= PACKET_DATA_SIZE
461-
) {
462-
j += 1;
463-
}
464-
const tx = new Transaction();
465-
for (let k = i; k < j - 1; k += 1) {
466-
tx.add(instructions[k]);
467-
}
468-
i = j - 1;
469-
txToSend.push(tx);
470-
}
471-
return txToSend;
472-
}
473-
474449
/** Get the size of instructions when serialized as in a remote executor payload */
475450
export function getSizeOfExecutorInstructions(
476451
instructions: TransactionInstruction[]
@@ -481,54 +456,6 @@ export function getSizeOfExecutorInstructions(
481456
})
482457
.reduce((a, b) => a + b);
483458
}
484-
/**
485-
* Get the size of a transaction that would contain the provided array of instructions
486-
*/
487-
export function getSizeOfTransaction(
488-
instructions: TransactionInstruction[]
489-
): number {
490-
const signers = new Set<string>();
491-
const accounts = new Set<string>();
492-
493-
instructions.map((ix) => {
494-
accounts.add(ix.programId.toBase58()),
495-
ix.keys.map((key) => {
496-
if (key.isSigner) {
497-
signers.add(key.pubkey.toBase58());
498-
}
499-
accounts.add(key.pubkey.toBase58());
500-
});
501-
});
502-
503-
const instruction_sizes: number = instructions
504-
.map(
505-
(ix) =>
506-
1 +
507-
getSizeOfCompressedU16(ix.keys.length) +
508-
ix.keys.length +
509-
getSizeOfCompressedU16(ix.data.length) +
510-
ix.data.length
511-
)
512-
.reduce((a, b) => a + b, 0);
513-
514-
return (
515-
1 +
516-
signers.size * 64 +
517-
3 +
518-
getSizeOfCompressedU16(accounts.size) +
519-
32 * accounts.size +
520-
32 +
521-
getSizeOfCompressedU16(instructions.length) +
522-
instruction_sizes
523-
);
524-
}
525-
526-
/**
527-
* Get the size of n in bytes when serialized as a CompressedU16
528-
*/
529-
export function getSizeOfCompressedU16(n: number) {
530-
return 1 + Number(n >= 128) + Number(n >= 16384);
531-
}
532459

533460
/**
534461
* Wrap `instruction` in a Wormhole message for remote execution

governance/xc_admin/packages/xc_admin_frontend/hooks/usePyth.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,11 @@ const usePyth = (): PythHookData => {
7474
connectionRef.current = connection
7575
;(async () => {
7676
try {
77-
const allPythAccounts = await connection.getProgramAccounts(
78-
getPythProgramKeyForCluster(cluster)
79-
)
77+
const allPythAccounts = [
78+
...(await connection.getProgramAccounts(
79+
getPythProgramKeyForCluster(cluster)
80+
)),
81+
]
8082
if (cancelled) return
8183
const priceRawConfigs: { [key: string]: PriceRawConfig } = {}
8284

0 commit comments

Comments
 (0)