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
This commit is contained in:
parent
38350421f6
commit
e986b69c9a
|
@ -32,4 +32,4 @@ jobs:
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo-test-sbf
|
run: cargo-test-sbf
|
||||||
- name: Run sdk tests
|
- name: Run sdk tests
|
||||||
run: cargo test --p pyth-solana-sdk
|
run: cargo test --package pyth-solana-receiver-state
|
||||||
|
|
|
@ -29,7 +29,8 @@
|
||||||
"bigint-buffer": "^1.1.5",
|
"bigint-buffer": "^1.1.5",
|
||||||
"ethers": "^5.7.2",
|
"ethers": "^5.7.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"typescript": "^4.9.4"
|
"typescript": "^4.9.4",
|
||||||
|
"@pythnetwork/solana-utils": "*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bn.js": "^5.1.1",
|
"@types/bn.js": "^5.1.1",
|
||||||
|
|
|
@ -15,19 +15,13 @@ import {
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import {
|
import {
|
||||||
batchIntoExecutorPayload,
|
batchIntoExecutorPayload,
|
||||||
batchIntoTransactions,
|
|
||||||
getSizeOfCompressedU16,
|
|
||||||
getSizeOfExecutorInstructions,
|
getSizeOfExecutorInstructions,
|
||||||
getSizeOfTransaction,
|
|
||||||
MAX_EXECUTOR_PAYLOAD_SIZE,
|
MAX_EXECUTOR_PAYLOAD_SIZE,
|
||||||
} from "..";
|
} from "..";
|
||||||
|
import {
|
||||||
it("Unit test compressed u16 size", async () => {
|
getSizeOfTransaction,
|
||||||
expect(getSizeOfCompressedU16(127)).toBe(1);
|
TransactionBuilder,
|
||||||
expect(getSizeOfCompressedU16(128)).toBe(2);
|
} from "@pythnetwork/solana-utils";
|
||||||
expect(getSizeOfCompressedU16(16383)).toBe(2);
|
|
||||||
expect(getSizeOfCompressedU16(16384)).toBe(3);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Unit test for getSizeOfTransaction", async () => {
|
it("Unit test for getSizeOfTransaction", async () => {
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(60000);
|
||||||
|
@ -84,7 +78,7 @@ it("Unit test for getSizeOfTransaction", async () => {
|
||||||
transaction.recentBlockhash = "GqdFtdM7zzWw33YyHtBNwPhyBsdYKcfm9gT47bWnbHvs"; // Mock blockhash from devnet
|
transaction.recentBlockhash = "GqdFtdM7zzWw33YyHtBNwPhyBsdYKcfm9gT47bWnbHvs"; // Mock blockhash from devnet
|
||||||
transaction.feePayer = payer.publicKey;
|
transaction.feePayer = payer.publicKey;
|
||||||
expect(transaction.serialize({ requireAllSignatures: false }).length).toBe(
|
expect(transaction.serialize({ requireAllSignatures: false }).length).toBe(
|
||||||
getSizeOfTransaction(ixsToSend)
|
getSizeOfTransaction(ixsToSend, false)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -115,13 +109,14 @@ it("Unit test for getSizeOfTransaction", async () => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const txToSend: Transaction[] = batchIntoTransactions(ixsToSend);
|
const txToSend: Transaction[] =
|
||||||
|
TransactionBuilder.batchIntoLegacyTransactions(ixsToSend);
|
||||||
expect(
|
expect(
|
||||||
txToSend.map((tx) => tx.instructions.length).reduce((a, b) => a + b)
|
txToSend.map((tx) => tx.instructions.length).reduce((a, b) => a + b)
|
||||||
).toBe(ixsToSend.length);
|
).toBe(ixsToSend.length);
|
||||||
expect(
|
expect(
|
||||||
txToSend.every(
|
txToSend.every(
|
||||||
(tx) => getSizeOfTransaction(tx.instructions) <= PACKET_DATA_SIZE
|
(tx) => getSizeOfTransaction(tx.instructions, false) <= PACKET_DATA_SIZE
|
||||||
)
|
)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
|
@ -129,7 +124,7 @@ it("Unit test for getSizeOfTransaction", async () => {
|
||||||
tx.recentBlockhash = "GqdFtdM7zzWw33YyHtBNwPhyBsdYKcfm9gT47bWnbHvs"; // Mock blockhash from devnet
|
tx.recentBlockhash = "GqdFtdM7zzWw33YyHtBNwPhyBsdYKcfm9gT47bWnbHvs"; // Mock blockhash from devnet
|
||||||
tx.feePayer = payer.publicKey;
|
tx.feePayer = payer.publicKey;
|
||||||
expect(tx.serialize({ requireAllSignatures: false }).length).toBe(
|
expect(tx.serialize({ requireAllSignatures: false }).length).toBe(
|
||||||
getSizeOfTransaction(tx.instructions)
|
getSizeOfTransaction(tx.instructions, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import SquadsMesh, { getIxAuthorityPDA, getTxPDA } from "@sqds/mesh";
|
||||||
import { MultisigAccount } from "@sqds/mesh/lib/types";
|
import { MultisigAccount } from "@sqds/mesh/lib/types";
|
||||||
import { mapKey } from "./remote_executor";
|
import { mapKey } from "./remote_executor";
|
||||||
import { WORMHOLE_ADDRESS } from "./wormhole";
|
import { WORMHOLE_ADDRESS } from "./wormhole";
|
||||||
|
import { TransactionBuilder } from "@pythnetwork/solana-utils";
|
||||||
|
|
||||||
export const MAX_EXECUTOR_PAYLOAD_SIZE = PACKET_DATA_SIZE - 687; // Bigger payloads won't fit in one addInstruction call when adding to the proposal
|
export const MAX_EXECUTOR_PAYLOAD_SIZE = PACKET_DATA_SIZE - 687; // Bigger payloads won't fit in one addInstruction call when adding to the proposal
|
||||||
export const MAX_INSTRUCTIONS_PER_PROPOSAL = 256 - 1;
|
export const MAX_INSTRUCTIONS_PER_PROPOSAL = 256 - 1;
|
||||||
|
@ -256,7 +257,7 @@ export class MultisigVault {
|
||||||
ixToSend.push(await this.activateProposalIx(proposalAddress));
|
ixToSend.push(await this.activateProposalIx(proposalAddress));
|
||||||
ixToSend.push(await this.approveProposalIx(proposalAddress));
|
ixToSend.push(await this.approveProposalIx(proposalAddress));
|
||||||
|
|
||||||
const txToSend = batchIntoTransactions(ixToSend);
|
const txToSend = TransactionBuilder.batchIntoLegacyTransactions(ixToSend);
|
||||||
await this.sendAllTransactions(txToSend);
|
await this.sendAllTransactions(txToSend);
|
||||||
return proposalAddress;
|
return proposalAddress;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +361,7 @@ export class MultisigVault {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const txToSend = batchIntoTransactions(ixToSend);
|
const txToSend = TransactionBuilder.batchIntoLegacyTransactions(ixToSend);
|
||||||
|
|
||||||
await this.sendAllTransactions(txToSend);
|
await this.sendAllTransactions(txToSend);
|
||||||
return newProposals;
|
return newProposals;
|
||||||
|
@ -445,32 +446,6 @@ export function batchIntoExecutorPayload(
|
||||||
return batches;
|
return batches;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Batch instructions into transactions
|
|
||||||
*/
|
|
||||||
export function batchIntoTransactions(
|
|
||||||
instructions: TransactionInstruction[]
|
|
||||||
): Transaction[] {
|
|
||||||
let i = 0;
|
|
||||||
const txToSend: Transaction[] = [];
|
|
||||||
while (i < instructions.length) {
|
|
||||||
let j = i + 2;
|
|
||||||
while (
|
|
||||||
j < instructions.length &&
|
|
||||||
getSizeOfTransaction(instructions.slice(i, j)) <= PACKET_DATA_SIZE
|
|
||||||
) {
|
|
||||||
j += 1;
|
|
||||||
}
|
|
||||||
const tx = new Transaction();
|
|
||||||
for (let k = i; k < j - 1; k += 1) {
|
|
||||||
tx.add(instructions[k]);
|
|
||||||
}
|
|
||||||
i = j - 1;
|
|
||||||
txToSend.push(tx);
|
|
||||||
}
|
|
||||||
return txToSend;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the size of instructions when serialized as in a remote executor payload */
|
/** Get the size of instructions when serialized as in a remote executor payload */
|
||||||
export function getSizeOfExecutorInstructions(
|
export function getSizeOfExecutorInstructions(
|
||||||
instructions: TransactionInstruction[]
|
instructions: TransactionInstruction[]
|
||||||
|
@ -481,54 +456,6 @@ export function getSizeOfExecutorInstructions(
|
||||||
})
|
})
|
||||||
.reduce((a, b) => a + b);
|
.reduce((a, b) => a + b);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Get the size of a transaction that would contain the provided array of instructions
|
|
||||||
*/
|
|
||||||
export function getSizeOfTransaction(
|
|
||||||
instructions: TransactionInstruction[]
|
|
||||||
): number {
|
|
||||||
const signers = new Set<string>();
|
|
||||||
const accounts = new Set<string>();
|
|
||||||
|
|
||||||
instructions.map((ix) => {
|
|
||||||
accounts.add(ix.programId.toBase58()),
|
|
||||||
ix.keys.map((key) => {
|
|
||||||
if (key.isSigner) {
|
|
||||||
signers.add(key.pubkey.toBase58());
|
|
||||||
}
|
|
||||||
accounts.add(key.pubkey.toBase58());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const instruction_sizes: number = instructions
|
|
||||||
.map(
|
|
||||||
(ix) =>
|
|
||||||
1 +
|
|
||||||
getSizeOfCompressedU16(ix.keys.length) +
|
|
||||||
ix.keys.length +
|
|
||||||
getSizeOfCompressedU16(ix.data.length) +
|
|
||||||
ix.data.length
|
|
||||||
)
|
|
||||||
.reduce((a, b) => a + b, 0);
|
|
||||||
|
|
||||||
return (
|
|
||||||
1 +
|
|
||||||
signers.size * 64 +
|
|
||||||
3 +
|
|
||||||
getSizeOfCompressedU16(accounts.size) +
|
|
||||||
32 * accounts.size +
|
|
||||||
32 +
|
|
||||||
getSizeOfCompressedU16(instructions.length) +
|
|
||||||
instruction_sizes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the size of n in bytes when serialized as a CompressedU16
|
|
||||||
*/
|
|
||||||
export function getSizeOfCompressedU16(n: number) {
|
|
||||||
return 1 + Number(n >= 128) + Number(n >= 16384);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap `instruction` in a Wormhole message for remote execution
|
* Wrap `instruction` in a Wormhole message for remote execution
|
||||||
|
|
|
@ -74,9 +74,11 @@ const usePyth = (): PythHookData => {
|
||||||
connectionRef.current = connection
|
connectionRef.current = connection
|
||||||
;(async () => {
|
;(async () => {
|
||||||
try {
|
try {
|
||||||
const allPythAccounts = await connection.getProgramAccounts(
|
const allPythAccounts = [
|
||||||
getPythProgramKeyForCluster(cluster)
|
...(await connection.getProgramAccounts(
|
||||||
)
|
getPythProgramKeyForCluster(cluster)
|
||||||
|
)),
|
||||||
|
]
|
||||||
if (cancelled) return
|
if (cancelled) return
|
||||||
const priceRawConfigs: { [key: string]: PriceRawConfig } = {}
|
const priceRawConfigs: { [key: string]: PriceRawConfig } = {}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
"target_chains/ethereum/examples/oracle_swap/app",
|
"target_chains/ethereum/examples/oracle_swap/app",
|
||||||
"target_chains/sui/sdk/js",
|
"target_chains/sui/sdk/js",
|
||||||
"target_chains/sui/cli",
|
"target_chains/sui/cli",
|
||||||
|
"target_chains/solana/sdk/js/solana_utils",
|
||||||
|
"target_chains/solana/sdk/js/pyth_solana_receiver",
|
||||||
"contract_manager"
|
"contract_manager"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -527,36 +529,6 @@
|
||||||
"protobufjs": "~6.11.2"
|
"protobufjs": "~6.11.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"contract_manager/node_modules/jayson": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/connect": "^3.4.33",
|
|
||||||
"@types/node": "^12.12.54",
|
|
||||||
"@types/ws": "^7.4.4",
|
|
||||||
"commander": "^2.20.3",
|
|
||||||
"delay": "^5.0.0",
|
|
||||||
"es6-promisify": "^5.0.0",
|
|
||||||
"eyes": "^0.1.8",
|
|
||||||
"isomorphic-ws": "^4.0.1",
|
|
||||||
"json-stringify-safe": "^5.0.1",
|
|
||||||
"JSONStream": "^1.3.5",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"ws": "^7.4.5"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"jayson": "bin/jayson.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"contract_manager/node_modules/jayson/node_modules/@types/node": {
|
|
||||||
"version": "12.20.55",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
|
||||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
|
|
||||||
},
|
|
||||||
"contract_manager/node_modules/protobufjs": {
|
"contract_manager/node_modules/protobufjs": {
|
||||||
"version": "6.11.3",
|
"version": "6.11.3",
|
||||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz",
|
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz",
|
||||||
|
@ -595,6 +567,7 @@
|
||||||
"version": "7.5.9",
|
"version": "7.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.3.0"
|
"node": ">=8.3.0"
|
||||||
},
|
},
|
||||||
|
@ -3397,6 +3370,7 @@
|
||||||
"@certusone/wormhole-sdk": "^0.9.22",
|
"@certusone/wormhole-sdk": "^0.9.22",
|
||||||
"@coral-xyz/anchor": "^0.26.0",
|
"@coral-xyz/anchor": "^0.26.0",
|
||||||
"@pythnetwork/client": "^2.17.0",
|
"@pythnetwork/client": "^2.17.0",
|
||||||
|
"@pythnetwork/solana-utils": "*",
|
||||||
"@solana/buffer-layout": "^4.0.1",
|
"@solana/buffer-layout": "^4.0.1",
|
||||||
"@solana/web3.js": "^1.73.0",
|
"@solana/web3.js": "^1.73.0",
|
||||||
"@sqds/mesh": "^1.0.6",
|
"@sqds/mesh": "^1.0.6",
|
||||||
|
@ -3821,36 +3795,6 @@
|
||||||
"node": ">=8.0.0"
|
"node": ">=8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"governance/xc_admin/packages/xc_admin_common/node_modules/jayson": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/connect": "^3.4.33",
|
|
||||||
"@types/node": "^12.12.54",
|
|
||||||
"@types/ws": "^7.4.4",
|
|
||||||
"commander": "^2.20.3",
|
|
||||||
"delay": "^5.0.0",
|
|
||||||
"es6-promisify": "^5.0.0",
|
|
||||||
"eyes": "^0.1.8",
|
|
||||||
"isomorphic-ws": "^4.0.1",
|
|
||||||
"json-stringify-safe": "^5.0.1",
|
|
||||||
"JSONStream": "^1.3.5",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"ws": "^7.4.5"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"jayson": "bin/jayson.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"governance/xc_admin/packages/xc_admin_common/node_modules/jayson/node_modules/@types/node": {
|
|
||||||
"version": "12.20.55",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
|
||||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
|
|
||||||
},
|
|
||||||
"governance/xc_admin/packages/xc_admin_common/node_modules/prettier": {
|
"governance/xc_admin/packages/xc_admin_common/node_modules/prettier": {
|
||||||
"version": "2.8.3",
|
"version": "2.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
|
||||||
|
@ -3920,6 +3864,7 @@
|
||||||
"version": "7.5.9",
|
"version": "7.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.3.0"
|
"node": ">=8.3.0"
|
||||||
},
|
},
|
||||||
|
@ -6471,16 +6416,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.21.5",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
|
||||||
"integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==",
|
"integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"regenerator-runtime": "^0.13.11"
|
"regenerator-runtime": "^0.14.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/runtime/node_modules/regenerator-runtime": {
|
||||||
|
"version": "0.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
||||||
|
},
|
||||||
"node_modules/@babel/template": {
|
"node_modules/@babel/template": {
|
||||||
"version": "7.20.7",
|
"version": "7.20.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
|
||||||
|
@ -13248,10 +13198,18 @@
|
||||||
"resolved": "target_chains/ethereum/sdk/solidity",
|
"resolved": "target_chains/ethereum/sdk/solidity",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@pythnetwork/pyth-solana-receiver": {
|
||||||
|
"resolved": "target_chains/solana/sdk/js/pyth_solana_receiver",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@pythnetwork/pyth-sui-js": {
|
"node_modules/@pythnetwork/pyth-sui-js": {
|
||||||
"resolved": "target_chains/sui/sdk/js",
|
"resolved": "target_chains/sui/sdk/js",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@pythnetwork/solana-utils": {
|
||||||
|
"resolved": "target_chains/solana/sdk/js/solana_utils",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/primitive": {
|
"node_modules/@radix-ui/primitive": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz",
|
||||||
|
@ -16274,37 +16232,48 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@solana/web3.js": {
|
"node_modules/@solana/web3.js": {
|
||||||
"version": "1.76.0",
|
"version": "1.90.0",
|
||||||
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.76.0.tgz",
|
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.90.0.tgz",
|
||||||
"integrity": "sha512-aJtF/nTs+9St+KtTK/wgVJ+SinfjYzn+3w1ygYIPw8ST6LH+qHBn8XkodgDTwlv/xzNkaVz1kkUDOZ8BPXyZWA==",
|
"integrity": "sha512-p0cb/COXb8NNVSMkGMPwqQ6NvObZgUitN80uOedMB+jbYWOKOeJBuPnzhenkIV9RX0krGwyuY1Ltn5O8MGFsEw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.23.4",
|
||||||
"@noble/curves": "^1.0.0",
|
"@noble/curves": "^1.2.0",
|
||||||
"@noble/hashes": "^1.3.0",
|
"@noble/hashes": "^1.3.2",
|
||||||
"@solana/buffer-layout": "^4.0.0",
|
"@solana/buffer-layout": "^4.0.1",
|
||||||
"agentkeepalive": "^4.2.1",
|
"agentkeepalive": "^4.5.0",
|
||||||
"bigint-buffer": "^1.1.5",
|
"bigint-buffer": "^1.1.5",
|
||||||
"bn.js": "^5.0.0",
|
"bn.js": "^5.2.1",
|
||||||
"borsh": "^0.7.0",
|
"borsh": "^0.7.0",
|
||||||
"bs58": "^4.0.1",
|
"bs58": "^4.0.1",
|
||||||
"buffer": "6.0.3",
|
"buffer": "6.0.3",
|
||||||
"fast-stable-stringify": "^1.0.0",
|
"fast-stable-stringify": "^1.0.0",
|
||||||
"jayson": "^3.4.4",
|
"jayson": "^4.1.0",
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "^2.7.0",
|
||||||
"rpc-websockets": "^7.5.1",
|
"rpc-websockets": "^7.5.1",
|
||||||
"superstruct": "^0.14.2"
|
"superstruct": "^0.14.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@solana/web3.js/node_modules/@noble/hashes": {
|
"node_modules/@solana/web3.js/node_modules/@noble/curves": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
|
||||||
"integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==",
|
"integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
|
||||||
"funding": [
|
"dependencies": {
|
||||||
{
|
"@noble/hashes": "1.3.3"
|
||||||
"type": "individual",
|
},
|
||||||
"url": "https://paulmillr.com/funding/"
|
"funding": {
|
||||||
}
|
"url": "https://paulmillr.com/funding/"
|
||||||
]
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@solana/web3.js/node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@solana/web3.js/node_modules/buffer": {
|
"node_modules/@solana/web3.js/node_modules/buffer": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
|
@ -22006,12 +21975,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/agentkeepalive": {
|
"node_modules/agentkeepalive": {
|
||||||
"version": "4.2.1",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
|
||||||
"integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==",
|
"integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.1.0",
|
|
||||||
"depd": "^1.1.2",
|
|
||||||
"humanize-ms": "^1.2.1"
|
"humanize-ms": "^1.2.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -34442,9 +34409,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jayson": {
|
"node_modules/jayson": {
|
||||||
"version": "3.7.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-3.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
||||||
"integrity": "sha512-tfy39KJMrrXJ+mFcMpxwBvFDetS8LAID93+rycFglIQM4kl3uNR3W4lBLE/FFhsoUCEox5Dt2adVpDm/XtebbQ==",
|
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/connect": "^3.4.33",
|
"@types/connect": "^3.4.33",
|
||||||
"@types/node": "^12.12.54",
|
"@types/node": "^12.12.54",
|
||||||
|
@ -34456,7 +34423,6 @@
|
||||||
"isomorphic-ws": "^4.0.1",
|
"isomorphic-ws": "^4.0.1",
|
||||||
"json-stringify-safe": "^5.0.1",
|
"json-stringify-safe": "^5.0.1",
|
||||||
"JSONStream": "^1.3.5",
|
"JSONStream": "^1.3.5",
|
||||||
"lodash": "^4.17.20",
|
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"ws": "^7.4.5"
|
"ws": "^7.4.5"
|
||||||
},
|
},
|
||||||
|
@ -58819,41 +58785,6 @@
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"target_chains/ethereum/contracts/node_modules/jayson": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/connect": "^3.4.33",
|
|
||||||
"@types/node": "^12.12.54",
|
|
||||||
"@types/ws": "^7.4.4",
|
|
||||||
"commander": "^2.20.3",
|
|
||||||
"delay": "^5.0.0",
|
|
||||||
"es6-promisify": "^5.0.0",
|
|
||||||
"eyes": "^0.1.8",
|
|
||||||
"isomorphic-ws": "^4.0.1",
|
|
||||||
"json-stringify-safe": "^5.0.1",
|
|
||||||
"JSONStream": "^1.3.5",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"ws": "^7.4.5"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"jayson": "bin/jayson.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"target_chains/ethereum/contracts/node_modules/jayson/node_modules/@types/node": {
|
|
||||||
"version": "12.20.55",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
|
||||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
|
|
||||||
},
|
|
||||||
"target_chains/ethereum/contracts/node_modules/jayson/node_modules/commander": {
|
|
||||||
"version": "2.20.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
|
||||||
},
|
|
||||||
"target_chains/ethereum/contracts/node_modules/jsonfile": {
|
"target_chains/ethereum/contracts/node_modules/jsonfile": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||||
|
@ -58949,6 +58880,7 @@
|
||||||
"version": "7.5.9",
|
"version": "7.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.3.0"
|
"node": ">=8.3.0"
|
||||||
},
|
},
|
||||||
|
@ -59598,6 +59530,107 @@
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"target_chains/solana/sdk/js/pyth_solana_receiver": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@coral-xyz/anchor": "^0.29.0",
|
||||||
|
"@pythnetwork/price-service-sdk": "*",
|
||||||
|
"@pythnetwork/solana-utils": "*",
|
||||||
|
"@solana/web3.js": "^1.90.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^29.4.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.20.0",
|
||||||
|
"@typescript-eslint/parser": "^5.20.0",
|
||||||
|
"eslint": "^8.13.0",
|
||||||
|
"jest": "^29.4.0",
|
||||||
|
"prettier": "^2.6.2",
|
||||||
|
"quicktype": "^23.0.76",
|
||||||
|
"ts-jest": "^29.0.5",
|
||||||
|
"typescript": "^4.6.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target_chains/solana/sdk/js/pyth_solana_receiver/node_modules/@coral-xyz/anchor": {
|
||||||
|
"version": "0.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@coral-xyz/anchor/-/anchor-0.29.0.tgz",
|
||||||
|
"integrity": "sha512-eny6QNG0WOwqV0zQ7cs/b1tIuzZGmP7U7EcH+ogt4Gdbl8HDmIYVMh/9aTmYZPaFWjtUaI8qSn73uYEXWfATdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@coral-xyz/borsh": "^0.29.0",
|
||||||
|
"@noble/hashes": "^1.3.1",
|
||||||
|
"@solana/web3.js": "^1.68.0",
|
||||||
|
"bn.js": "^5.1.2",
|
||||||
|
"bs58": "^4.0.1",
|
||||||
|
"buffer-layout": "^1.2.2",
|
||||||
|
"camelcase": "^6.3.0",
|
||||||
|
"cross-fetch": "^3.1.5",
|
||||||
|
"crypto-hash": "^1.3.0",
|
||||||
|
"eventemitter3": "^4.0.7",
|
||||||
|
"pako": "^2.0.3",
|
||||||
|
"snake-case": "^3.0.4",
|
||||||
|
"superstruct": "^0.15.4",
|
||||||
|
"toml": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target_chains/solana/sdk/js/pyth_solana_receiver/node_modules/@coral-xyz/borsh": {
|
||||||
|
"version": "0.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.29.0.tgz",
|
||||||
|
"integrity": "sha512-s7VFVa3a0oqpkuRloWVPdCK7hMbAMY270geZOGfCnaqexrP5dTIpbEHL33req6IYPPJ0hYa71cdvJ1h6V55/oQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"bn.js": "^5.1.2",
|
||||||
|
"buffer-layout": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@solana/web3.js": "^1.68.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target_chains/solana/sdk/js/pyth_solana_receiver/node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target_chains/solana/sdk/js/pyth_solana_receiver/node_modules/camelcase": {
|
||||||
|
"version": "6.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
|
||||||
|
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target_chains/solana/sdk/js/solana_utils": {
|
||||||
|
"name": "@pythnetwork/solana-utils",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@solana/web3.js": "^1.90.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^29.4.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.20.0",
|
||||||
|
"@typescript-eslint/parser": "^5.20.0",
|
||||||
|
"eslint": "^8.13.0",
|
||||||
|
"jest": "^29.4.0",
|
||||||
|
"prettier": "^2.6.2",
|
||||||
|
"quicktype": "^23.0.76",
|
||||||
|
"ts-jest": "^29.0.5",
|
||||||
|
"typescript": "^4.6.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"target_chains/sui/cli": {
|
"target_chains/sui/cli": {
|
||||||
"name": "pyth-sui-cli",
|
"name": "pyth-sui-cli",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
|
@ -60047,36 +60080,6 @@
|
||||||
"node-fetch": "^2.6.12"
|
"node-fetch": "^2.6.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"target_chains/sui/cli/node_modules/jayson": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/connect": "^3.4.33",
|
|
||||||
"@types/node": "^12.12.54",
|
|
||||||
"@types/ws": "^7.4.4",
|
|
||||||
"commander": "^2.20.3",
|
|
||||||
"delay": "^5.0.0",
|
|
||||||
"es6-promisify": "^5.0.0",
|
|
||||||
"eyes": "^0.1.8",
|
|
||||||
"isomorphic-ws": "^4.0.1",
|
|
||||||
"json-stringify-safe": "^5.0.1",
|
|
||||||
"JSONStream": "^1.3.5",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"ws": "^7.4.5"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"jayson": "bin/jayson.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"target_chains/sui/cli/node_modules/jayson/node_modules/@types/node": {
|
|
||||||
"version": "12.20.55",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
|
||||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
|
|
||||||
},
|
|
||||||
"target_chains/sui/cli/node_modules/prettier": {
|
"target_chains/sui/cli/node_modules/prettier": {
|
||||||
"version": "2.8.8",
|
"version": "2.8.8",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
||||||
|
@ -60141,6 +60144,7 @@
|
||||||
"version": "7.5.9",
|
"version": "7.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.3.0"
|
"node": ">=8.3.0"
|
||||||
},
|
},
|
||||||
|
@ -61783,11 +61787,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/runtime": {
|
"@babel/runtime": {
|
||||||
"version": "7.21.5",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
|
||||||
"integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==",
|
"integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.13.11"
|
"regenerator-runtime": "^0.14.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/template": {
|
"@babel/template": {
|
||||||
|
@ -70538,37 +70549,6 @@
|
||||||
"path-is-absolute": "^1.0.0"
|
"path-is-absolute": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jayson": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
|
||||||
"requires": {
|
|
||||||
"@types/connect": "^3.4.33",
|
|
||||||
"@types/node": "^12.12.54",
|
|
||||||
"@types/ws": "^7.4.4",
|
|
||||||
"commander": "^2.20.3",
|
|
||||||
"delay": "^5.0.0",
|
|
||||||
"es6-promisify": "^5.0.0",
|
|
||||||
"eyes": "^0.1.8",
|
|
||||||
"isomorphic-ws": "^4.0.1",
|
|
||||||
"json-stringify-safe": "^5.0.1",
|
|
||||||
"JSONStream": "^1.3.5",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"ws": "^7.4.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": {
|
|
||||||
"version": "12.20.55",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
|
||||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
|
|
||||||
},
|
|
||||||
"commander": {
|
|
||||||
"version": "2.20.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jsonfile": {
|
"jsonfile": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||||
|
@ -70641,6 +70621,7 @@
|
||||||
"version": "7.5.9",
|
"version": "7.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"optional": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71515,6 +71496,66 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@pythnetwork/pyth-solana-receiver": {
|
||||||
|
"version": "file:target_chains/solana/sdk/js/pyth_solana_receiver",
|
||||||
|
"requires": {
|
||||||
|
"@coral-xyz/anchor": "^0.29.0",
|
||||||
|
"@pythnetwork/price-service-sdk": "*",
|
||||||
|
"@pythnetwork/solana-utils": "*",
|
||||||
|
"@solana/web3.js": "^1.90.0",
|
||||||
|
"@types/jest": "^29.4.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.20.0",
|
||||||
|
"@typescript-eslint/parser": "^5.20.0",
|
||||||
|
"eslint": "^8.13.0",
|
||||||
|
"jest": "^29.4.0",
|
||||||
|
"prettier": "^2.6.2",
|
||||||
|
"quicktype": "^23.0.76",
|
||||||
|
"ts-jest": "^29.0.5",
|
||||||
|
"typescript": "^4.6.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@coral-xyz/anchor": {
|
||||||
|
"version": "0.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@coral-xyz/anchor/-/anchor-0.29.0.tgz",
|
||||||
|
"integrity": "sha512-eny6QNG0WOwqV0zQ7cs/b1tIuzZGmP7U7EcH+ogt4Gdbl8HDmIYVMh/9aTmYZPaFWjtUaI8qSn73uYEXWfATdA==",
|
||||||
|
"requires": {
|
||||||
|
"@coral-xyz/borsh": "^0.29.0",
|
||||||
|
"@noble/hashes": "^1.3.1",
|
||||||
|
"@solana/web3.js": "^1.68.0",
|
||||||
|
"bn.js": "^5.1.2",
|
||||||
|
"bs58": "^4.0.1",
|
||||||
|
"buffer-layout": "^1.2.2",
|
||||||
|
"camelcase": "^6.3.0",
|
||||||
|
"cross-fetch": "^3.1.5",
|
||||||
|
"crypto-hash": "^1.3.0",
|
||||||
|
"eventemitter3": "^4.0.7",
|
||||||
|
"pako": "^2.0.3",
|
||||||
|
"snake-case": "^3.0.4",
|
||||||
|
"superstruct": "^0.15.4",
|
||||||
|
"toml": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@coral-xyz/borsh": {
|
||||||
|
"version": "0.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.29.0.tgz",
|
||||||
|
"integrity": "sha512-s7VFVa3a0oqpkuRloWVPdCK7hMbAMY270geZOGfCnaqexrP5dTIpbEHL33req6IYPPJ0hYa71cdvJ1h6V55/oQ==",
|
||||||
|
"requires": {
|
||||||
|
"bn.js": "^5.1.2",
|
||||||
|
"buffer-layout": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@noble/hashes": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA=="
|
||||||
|
},
|
||||||
|
"camelcase": {
|
||||||
|
"version": "6.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
|
||||||
|
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@pythnetwork/pyth-sui-js": {
|
"@pythnetwork/pyth-sui-js": {
|
||||||
"version": "file:target_chains/sui/sdk/js",
|
"version": "file:target_chains/sui/sdk/js",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -71581,6 +71622,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@pythnetwork/solana-utils": {
|
||||||
|
"version": "file:target_chains/solana/sdk/js/solana_utils",
|
||||||
|
"requires": {
|
||||||
|
"@solana/web3.js": "^1.90.0",
|
||||||
|
"@types/jest": "^29.4.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.20.0",
|
||||||
|
"@typescript-eslint/parser": "^5.20.0",
|
||||||
|
"eslint": "^8.13.0",
|
||||||
|
"jest": "^29.4.0",
|
||||||
|
"prettier": "^2.6.2",
|
||||||
|
"quicktype": "^23.0.76",
|
||||||
|
"ts-jest": "^29.0.5",
|
||||||
|
"typescript": "^4.6.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@radix-ui/primitive": {
|
"@radix-ui/primitive": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz",
|
||||||
|
@ -73818,31 +73874,39 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@solana/web3.js": {
|
"@solana/web3.js": {
|
||||||
"version": "1.76.0",
|
"version": "1.90.0",
|
||||||
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.76.0.tgz",
|
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.90.0.tgz",
|
||||||
"integrity": "sha512-aJtF/nTs+9St+KtTK/wgVJ+SinfjYzn+3w1ygYIPw8ST6LH+qHBn8XkodgDTwlv/xzNkaVz1kkUDOZ8BPXyZWA==",
|
"integrity": "sha512-p0cb/COXb8NNVSMkGMPwqQ6NvObZgUitN80uOedMB+jbYWOKOeJBuPnzhenkIV9RX0krGwyuY1Ltn5O8MGFsEw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.23.4",
|
||||||
"@noble/curves": "^1.0.0",
|
"@noble/curves": "^1.2.0",
|
||||||
"@noble/hashes": "^1.3.0",
|
"@noble/hashes": "^1.3.2",
|
||||||
"@solana/buffer-layout": "^4.0.0",
|
"@solana/buffer-layout": "^4.0.1",
|
||||||
"agentkeepalive": "^4.2.1",
|
"agentkeepalive": "^4.5.0",
|
||||||
"bigint-buffer": "^1.1.5",
|
"bigint-buffer": "^1.1.5",
|
||||||
"bn.js": "^5.0.0",
|
"bn.js": "^5.2.1",
|
||||||
"borsh": "^0.7.0",
|
"borsh": "^0.7.0",
|
||||||
"bs58": "^4.0.1",
|
"bs58": "^4.0.1",
|
||||||
"buffer": "6.0.3",
|
"buffer": "6.0.3",
|
||||||
"fast-stable-stringify": "^1.0.0",
|
"fast-stable-stringify": "^1.0.0",
|
||||||
"jayson": "^3.4.4",
|
"jayson": "^4.1.0",
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "^2.7.0",
|
||||||
"rpc-websockets": "^7.5.1",
|
"rpc-websockets": "^7.5.1",
|
||||||
"superstruct": "^0.14.2"
|
"superstruct": "^0.14.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@noble/hashes": {
|
"@noble/curves": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
|
||||||
"integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg=="
|
"integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
|
||||||
|
"requires": {
|
||||||
|
"@noble/hashes": "1.3.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@noble/hashes": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA=="
|
||||||
},
|
},
|
||||||
"buffer": {
|
"buffer": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
|
@ -78597,12 +78661,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"agentkeepalive": {
|
"agentkeepalive": {
|
||||||
"version": "4.2.1",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
|
||||||
"integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==",
|
"integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^4.1.0",
|
|
||||||
"depd": "^1.1.2",
|
|
||||||
"humanize-ms": "^1.2.1"
|
"humanize-ms": "^1.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -81883,32 +81945,6 @@
|
||||||
"protobufjs": "~6.11.2"
|
"protobufjs": "~6.11.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jayson": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
|
||||||
"requires": {
|
|
||||||
"@types/connect": "^3.4.33",
|
|
||||||
"@types/node": "^12.12.54",
|
|
||||||
"@types/ws": "^7.4.4",
|
|
||||||
"commander": "^2.20.3",
|
|
||||||
"delay": "^5.0.0",
|
|
||||||
"es6-promisify": "^5.0.0",
|
|
||||||
"eyes": "^0.1.8",
|
|
||||||
"isomorphic-ws": "^4.0.1",
|
|
||||||
"json-stringify-safe": "^5.0.1",
|
|
||||||
"JSONStream": "^1.3.5",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"ws": "^7.4.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": {
|
|
||||||
"version": "12.20.55",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
|
||||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"protobufjs": {
|
"protobufjs": {
|
||||||
"version": "6.11.3",
|
"version": "6.11.3",
|
||||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz",
|
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz",
|
||||||
|
@ -81939,6 +81975,7 @@
|
||||||
"version": "7.5.9",
|
"version": "7.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"optional": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88900,9 +88937,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jayson": {
|
"jayson": {
|
||||||
"version": "3.7.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-3.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
||||||
"integrity": "sha512-tfy39KJMrrXJ+mFcMpxwBvFDetS8LAID93+rycFglIQM4kl3uNR3W4lBLE/FFhsoUCEox5Dt2adVpDm/XtebbQ==",
|
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/connect": "^3.4.33",
|
"@types/connect": "^3.4.33",
|
||||||
"@types/node": "^12.12.54",
|
"@types/node": "^12.12.54",
|
||||||
|
@ -88914,7 +88951,6 @@
|
||||||
"isomorphic-ws": "^4.0.1",
|
"isomorphic-ws": "^4.0.1",
|
||||||
"json-stringify-safe": "^5.0.1",
|
"json-stringify-safe": "^5.0.1",
|
||||||
"JSONStream": "^1.3.5",
|
"JSONStream": "^1.3.5",
|
||||||
"lodash": "^4.17.20",
|
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"ws": "^7.4.5"
|
"ws": "^7.4.5"
|
||||||
},
|
},
|
||||||
|
@ -97094,32 +97130,6 @@
|
||||||
"node-fetch": "^2.6.12"
|
"node-fetch": "^2.6.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jayson": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
|
||||||
"requires": {
|
|
||||||
"@types/connect": "^3.4.33",
|
|
||||||
"@types/node": "^12.12.54",
|
|
||||||
"@types/ws": "^7.4.4",
|
|
||||||
"commander": "^2.20.3",
|
|
||||||
"delay": "^5.0.0",
|
|
||||||
"es6-promisify": "^5.0.0",
|
|
||||||
"eyes": "^0.1.8",
|
|
||||||
"isomorphic-ws": "^4.0.1",
|
|
||||||
"json-stringify-safe": "^5.0.1",
|
|
||||||
"JSONStream": "^1.3.5",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"ws": "^7.4.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": {
|
|
||||||
"version": "12.20.55",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
|
||||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"version": "2.8.8",
|
"version": "2.8.8",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
||||||
|
@ -97160,6 +97170,7 @@
|
||||||
"version": "7.5.9",
|
"version": "7.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"optional": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105908,6 +105919,7 @@
|
||||||
"@certusone/wormhole-sdk": "^0.9.22",
|
"@certusone/wormhole-sdk": "^0.9.22",
|
||||||
"@coral-xyz/anchor": "^0.26.0",
|
"@coral-xyz/anchor": "^0.26.0",
|
||||||
"@pythnetwork/client": "^2.17.0",
|
"@pythnetwork/client": "^2.17.0",
|
||||||
|
"@pythnetwork/solana-utils": "*",
|
||||||
"@solana/buffer-layout": "^4.0.1",
|
"@solana/buffer-layout": "^4.0.1",
|
||||||
"@solana/web3.js": "^1.73.0",
|
"@solana/web3.js": "^1.73.0",
|
||||||
"@sqds/mesh": "^1.0.6",
|
"@sqds/mesh": "^1.0.6",
|
||||||
|
@ -106298,32 +106310,6 @@
|
||||||
"pure-rand": "^6.0.0"
|
"pure-rand": "^6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jayson": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
|
|
||||||
"requires": {
|
|
||||||
"@types/connect": "^3.4.33",
|
|
||||||
"@types/node": "^12.12.54",
|
|
||||||
"@types/ws": "^7.4.4",
|
|
||||||
"commander": "^2.20.3",
|
|
||||||
"delay": "^5.0.0",
|
|
||||||
"es6-promisify": "^5.0.0",
|
|
||||||
"eyes": "^0.1.8",
|
|
||||||
"isomorphic-ws": "^4.0.1",
|
|
||||||
"json-stringify-safe": "^5.0.1",
|
|
||||||
"JSONStream": "^1.3.5",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"ws": "^7.4.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": {
|
|
||||||
"version": "12.20.55",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
|
||||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"version": "2.8.3",
|
"version": "2.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
|
||||||
|
@ -106366,6 +106352,7 @@
|
||||||
"version": "7.5.9",
|
"version": "7.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"optional": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
"target_chains/ethereum/examples/oracle_swap/app",
|
"target_chains/ethereum/examples/oracle_swap/app",
|
||||||
"target_chains/sui/sdk/js",
|
"target_chains/sui/sdk/js",
|
||||||
"target_chains/sui/cli",
|
"target_chains/sui/cli",
|
||||||
|
"target_chains/solana/sdk/js/solana_utils",
|
||||||
|
"target_chains/solana/sdk/js/pyth_solana_receiver",
|
||||||
"contract_manager"
|
"contract_manager"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -1,11 +1,25 @@
|
||||||
|
import BN from "bn.js";
|
||||||
|
|
||||||
const ACCUMULATOR_MAGIC = "504e4155";
|
const ACCUMULATOR_MAGIC = "504e4155";
|
||||||
const MAJOR_VERSION = 1;
|
const MAJOR_VERSION = 1;
|
||||||
const MINOR_VERSION = 0;
|
const MINOR_VERSION = 0;
|
||||||
const KECCAK160_HASH_SIZE = 20;
|
const KECCAK160_HASH_SIZE = 20;
|
||||||
|
const PRICE_FEED_MESSAGE_VARIANT = 0;
|
||||||
|
|
||||||
export type AccumulatorUpdateData = {
|
export type AccumulatorUpdateData = {
|
||||||
vaa: Buffer;
|
vaa: Buffer;
|
||||||
updates: { message: Buffer; proof: Buffer[] }[];
|
updates: { message: Buffer; proof: number[][] }[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PriceFeedMessage = {
|
||||||
|
feedId: Buffer;
|
||||||
|
price: BN;
|
||||||
|
confidence: BN;
|
||||||
|
exponent: number;
|
||||||
|
publishTime: BN;
|
||||||
|
prevPublishTime: BN;
|
||||||
|
emaPrice: BN;
|
||||||
|
emaConf: BN;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function isAccumulatorUpdateData(updateBytes: Buffer): boolean {
|
export function isAccumulatorUpdateData(updateBytes: Buffer): boolean {
|
||||||
|
@ -15,6 +29,40 @@ export function isAccumulatorUpdateData(updateBytes: Buffer): boolean {
|
||||||
updateBytes[5] === MINOR_VERSION
|
updateBytes[5] === MINOR_VERSION
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
export function parsePriceFeedMessage(message: Buffer): PriceFeedMessage {
|
||||||
|
let cursor = 0;
|
||||||
|
const variant = message.readUInt8(cursor);
|
||||||
|
if (variant !== PRICE_FEED_MESSAGE_VARIANT) {
|
||||||
|
throw new Error("Not a price feed message");
|
||||||
|
}
|
||||||
|
cursor += 1;
|
||||||
|
const feedId = message.subarray(cursor, cursor + 32);
|
||||||
|
cursor += 32;
|
||||||
|
const price = new BN(message.subarray(cursor, cursor + 8), "be");
|
||||||
|
cursor += 8;
|
||||||
|
const confidence = new BN(message.subarray(cursor, cursor + 8), "be");
|
||||||
|
cursor += 8;
|
||||||
|
const exponent = message.readInt32BE(cursor);
|
||||||
|
cursor += 4;
|
||||||
|
const publishTime = new BN(message.subarray(cursor, cursor + 8), "be");
|
||||||
|
cursor += 8;
|
||||||
|
const prevPublishTime = new BN(message.subarray(cursor, cursor + 8), "be");
|
||||||
|
cursor += 8;
|
||||||
|
const emaPrice = new BN(message.subarray(cursor, cursor + 8), "be");
|
||||||
|
cursor += 8;
|
||||||
|
const emaConf = new BN(message.subarray(cursor, cursor + 8), "be");
|
||||||
|
cursor += 8;
|
||||||
|
return {
|
||||||
|
feedId,
|
||||||
|
price,
|
||||||
|
confidence,
|
||||||
|
exponent,
|
||||||
|
publishTime,
|
||||||
|
prevPublishTime,
|
||||||
|
emaPrice,
|
||||||
|
emaConf,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function parseAccumulatorUpdateData(
|
export function parseAccumulatorUpdateData(
|
||||||
data: Buffer
|
data: Buffer
|
||||||
|
@ -50,7 +98,9 @@ export function parseAccumulatorUpdateData(
|
||||||
cursor += 1;
|
cursor += 1;
|
||||||
const proof = [];
|
const proof = [];
|
||||||
for (let j = 0; j < numProofs; j++) {
|
for (let j = 0; j < numProofs; j++) {
|
||||||
proof.push(data.subarray(cursor, cursor + KECCAK160_HASH_SIZE));
|
proof.push(
|
||||||
|
Array.from(data.subarray(cursor, cursor + KECCAK160_HASH_SIZE))
|
||||||
|
);
|
||||||
cursor += KECCAK160_HASH_SIZE;
|
cursor += KECCAK160_HASH_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,28 @@
|
||||||
import { parseAccumulatorUpdateData } from "../AccumulatorUpdateData";
|
import {
|
||||||
|
parseAccumulatorUpdateData,
|
||||||
|
parsePriceFeedMessage,
|
||||||
|
} from "../AccumulatorUpdateData";
|
||||||
|
|
||||||
// This is just a sample update data from hermes
|
// This is just a sample update data from hermes
|
||||||
const TEST_ACCUMULATOR_UPDATE_DATA =
|
const TEST_ACCUMULATOR_UPDATE_DATA =
|
||||||
"UE5BVQEAAAADuAEAAAADDQCRWcud7VE0FQkptV7iZh1Ls8O4dszQ4HmdOZLNDVQiQnMB5Q9jVd52Y9IMI8k1QhOhT2xn82hveqZ6AIn+c6vPAQL4nN+ynbzaJnbGFpWW5ysEA811BblKr+DXO5I5tD3SgEjPmByPIEVPHRqdgnq7M8r6AG4q8qfbmeonROr67i4eAAPVteKrUXD6f13GG/Qj0xHcJ/NuR+xwrbs6KGmYZHq0fHv4m0C3LPIOgVo9iy2ednK5IB/pAEMoaGK/fwoL2ouSAQSulF0XQGZ0J5oFKvCwPBSZOYtITwEQSicnwIWu9a+j7SjMh/zF4vtqWFAqfkFatVMZI6/dkQkmwlcMkEkGHvN5AQZYiYD8teZVpmCzn9jxZo/qTF4qrWgrHWv3/i4kZsXmkDSq1QTiYd7ikQQVWVxgH3PKl03SPFvqoc7SmwKIZKyyAQjfPTwpqeTTi0zFRyyb9HKMYjcbXEcuRXn7uOaNF83ry1s+cudCcWsiaCNYEPzv1BvHxgYYXcx2MkNxUbXiLlmoAQpQSpOkNb9780k2EsrUjZd/ieD+sTQA6P0iZWL5jA8ONEi46mAufCfRlAO2a5jfUvjuN4Z/ZOklgT9eZ7v3JoleAAv/2wkZ5rQx+cl/jlL9k6rbzrDU8sYLTJnlFTsuOr66/iVUqCe0Clwv682NgvH8yLbtw9He/vdn3OeLn19eDU0qAQxk47DIhc9EAtNrdhFSyAoEBtQtgcxRvSnjIIMPTGIhIzv52WFY/I2CwyKcQLhERdjjfh7EhZvBUXHTFRk2xjc2AA3wNaGbjUXsJqL8VyBQg7t0dILbUQ8AiOZJQVfx+L+1mFVZAc4v8/0BWsIF5b7+YmoN6psArWCvZcd9Hkjuxda4AQ5Rxgs32U2Jm43W4voTk42MibgvPMas3xQbuCW88pH1skdSTfvtgoIOa6BdoS3YEUJu78a0X3AiIUem1fDOdOs7AA/lHyqNz4vwuTNs8U6G51VqO2g1yEJyRwrMqsjEvK9VC0EjieacqPBwPL9/DMssbHU01bL+YzEY5XTxi1QiBeyFABJuE+6jHgEh9WvwaPDZe7me9sl5EiPDUxAAryErsB0LDTrnzls7qgDymCp+MSJur8U4I08ul/mL1rVesK3uUqqtAGV20Z0AAAAAABrhAfrtrFhR4yubI7X5QRqMK6xKrj7U3XuBHdGnLqSqcQAAAAAB1IYyAUFVV1YAAAAAAAbbm1gAACcQralfDHbB9c321F6ngWz+RspcmdsBAFUAyWRY05P+net6fWOgrEHiiYpnp3UNvRZmcyeeBsho3woAAAAAAFEIJAAAAAAAAAxT////+AAAAABldtGcAAAAAGV20ZsAAAAAAFEWJQAAAAAAAAu6CqMvc3++cZquwewCu6kJe8aPB1SFPI41uwi10MgNwqRbCue30EvorUjF4mKpFB+Cwx8KH5bFnAAX13DPmu7OCbX7k0LdKtr9pb8zPVsXwlx+BteFyBWNtJmeLIx7tG88H2uARL/B+MJw2GcVujs6qdnIQkIjjBdDIR3XRtY2zMfK58eeXuiAkJDHIQ3H41GmYRAVe8FtPvtMWTY51Q63Tkmfq60qsB1yy4Srd5QI/x60eBnOlAYC67+gjB0sGHLrjSapbXzGUf//";
|
"UE5BVQEAAAADuAEAAAADDQILBDsleD7xENCN7O7KjXAe15OQQ8FvD0E6L+bIemppBjNEZEOF0XuxCPQ/ti4gWUplKpieCWYiibuaDvXOeSFFAQOuYekUPV6yqK2BRWo/KRmJ00SV01OJDRhNzc1YnzUi+j8dt1tNBkVY99NIs5leyixUmeq4Dn1n8y37xN4JtAacAQSxJzGeZ6tejBD1YlPBlVwaCX8crkp19R1es7rDBhX/iit2plz5grz66fPj/mpoffZqKo95Fq/0sxWHIvn4nhgXAQYLl99cpa6KlaA8q1Pj7sN6TXNrXtmTBlzRU6dZ0ptO8VKp4K3zkVqbWkB5mbHCeuYNgOGMCnVsS7Ce9J7NganNAQf0nyez/5yR/U2zu+XRbi8eNzI1yJ9Hc4lmMl8pTPPQRgrs9HyiVCliCOcHdLzLio3JoLBhmFxQ3ygYj2eB+k3UAQgHX1e/+vbCjBNnmx/UQV8m0y/wifKAMfYpK4mR8voG3wgxo5MIFUvvCZ9/Gt1GizTX5CuoQD9J4ioxjoCFghVtAQqG5lFSpVRpC0dQlMv2ju2K89Ph0tJGsX7LGRXRnh9lEkkM8W+Uxf1R50HFsZHiXU08Grz0mKRPavesrzD+1xYGAQuYL6q5SagvBS7TfZJYS4kUMw74TvMiHLWx2ps3EdEJbh3WCWGfOM3amrplQBnqctDYh3StqspyTdaU5QTxfyYvAQwNWdPBEtAR6yIHB8KYrEDGGUH91uqD768NGigW6ziLwnNw2un+gcDUiafL3pZpqC4yIDhmnEz26PmQs4cAI5nkAA3/Zl3Pt7fLG3E5xBa/lbdrBUT3J+znFExbuFZuZipvbBwnQq/yyBSXqyfuHG3GTQZ/wXBto5zUEyex9889XYzaAQ52EUUCG0X4i0nWHeAf00+s6cODkW6hanQ1MHfTdvvVMXqK9nfvicz8pBna/NVp1wiTN5zR9rWjQuAf0g0c6TRLARCPT46a0/3xER/tV7WLQ6JQUWHMbV0G6cXKmdFT0Qg3/m08Dlabic+EHW9u2ugZA5sJ/Jl4oGk/lWLJoNoxDFMZARJgsgN2RdhjvJMRmf/Kj0d5PSvI7kE+J7ShlJd5058+ETZVPR15fJpT3BWUJ8i/vdGmU90A6iGyXRmNRBFx21qqAGXeGOEAAAAAABrhAfrtrFhR4yubI7X5QRqMK6xKrj7U3XuBHdGnLqSqcQAAAAACjFEsAUFVV1YAAAAAAAeUpesAACcQy5naBQ5EEmAnr2RvKBD1SUJH9zwBAFUA7w2Lb9os66QdoV1AldHaOSoNL47Qxse8D0z6yMKAtW0AAAACgAWPuQAAAAAAX+C0////+AAAAABl3hjhAAAAAGXeGOEAAAACgrM/OAAAAAAAaAvYCuE9uKnM0BlXJ1E/fLYtWytcVLhkSCzHW9p1ReYbPMt07qbcN5KykfYDlCJxjBT3UmyTbhTT30PmOLkZu9zraLg22Wysdg1W67WoQZi654djZPBpAiHRU2KQXbDSGqJcekD0W+TqKO+QagPAoXksP0iMGEYpBdVZKGhSvw0NpXv/5Qb5NHO/+dTahPFBgXJH+9geJaxYru9ZRMg5o+YjIvkwuom/2NP0mTbfp4syeDQBs+fmcdGmAjgcdF0wt1gR6kYbsWQ/CZ08";
|
||||||
|
|
||||||
describe("Test parse accumulator update", () => {
|
describe("Test parse accumulator update", () => {
|
||||||
test("Happy path", async () => {
|
test("Happy path", async () => {
|
||||||
parseAccumulatorUpdateData(
|
const { vaa, updates } = parseAccumulatorUpdateData(
|
||||||
Buffer.from(TEST_ACCUMULATOR_UPDATE_DATA, "base64")
|
Buffer.from(TEST_ACCUMULATOR_UPDATE_DATA, "base64")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const priceMessage = parsePriceFeedMessage(updates[0].message);
|
||||||
|
expect(priceMessage.feedId.toString("hex")).toBe(
|
||||||
|
"ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"
|
||||||
|
);
|
||||||
|
expect(priceMessage.price.toString()).toBe("10737782713");
|
||||||
|
expect(priceMessage.confidence.toString()).toBe("6283444");
|
||||||
|
expect(priceMessage.exponent).toBe(-8);
|
||||||
|
expect(priceMessage.publishTime.toString()).toBe("1709054177");
|
||||||
|
expect(priceMessage.prevPublishTime.toString()).toBe("1709054177");
|
||||||
|
expect(priceMessage.emaPrice.toString()).toBe("10782719800");
|
||||||
|
expect(priceMessage.emaConf.toString()).toBe("6818776");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Wrong magic number", async () => {
|
test("Wrong magic number", async () => {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { isAccumulatorUpdateData } from "./AccumulatorUpdateData";
|
|
||||||
import {
|
import {
|
||||||
Convert,
|
Convert,
|
||||||
Price as JsonPrice,
|
Price as JsonPrice,
|
||||||
|
@ -14,6 +13,7 @@ export {
|
||||||
isAccumulatorUpdateData,
|
isAccumulatorUpdateData,
|
||||||
parseAccumulatorUpdateData,
|
parseAccumulatorUpdateData,
|
||||||
AccumulatorUpdateData,
|
AccumulatorUpdateData,
|
||||||
|
parsePriceFeedMessage,
|
||||||
} from "./AccumulatorUpdateData";
|
} from "./AccumulatorUpdateData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
target
|
target
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
node_modules
|
node_modules
|
||||||
|
lib
|
||||||
test-ledger
|
test-ledger
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
plugins: ["@typescript-eslint"],
|
||||||
|
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"name": "@pythnetwork/pyth-solana-receiver",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Pyth solana receiver SDK",
|
||||||
|
"homepage": "https://pyth.network",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"types": "lib/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"lib/**/*"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/pyth-network/pyth-crosschain.git",
|
||||||
|
"directory": "target_chains/solana/sdk/js"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"format": "prettier --write \"src/**/*.ts\"",
|
||||||
|
"lint": "eslint src/",
|
||||||
|
"prepublishOnly": "npm run build && npm test && npm run lint",
|
||||||
|
"preversion": "npm run lint",
|
||||||
|
"version": "npm run format && git add -A src"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"pyth",
|
||||||
|
"oracle"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^29.4.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.20.0",
|
||||||
|
"@typescript-eslint/parser": "^5.20.0",
|
||||||
|
"eslint": "^8.13.0",
|
||||||
|
"jest": "^29.4.0",
|
||||||
|
"prettier": "^2.6.2",
|
||||||
|
"quicktype": "^23.0.76",
|
||||||
|
"ts-jest": "^29.0.5",
|
||||||
|
"typescript": "^4.6.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@coral-xyz/anchor": "^0.29.0",
|
||||||
|
"@pythnetwork/price-service-sdk": "*",
|
||||||
|
"@pythnetwork/solana-utils": "*",
|
||||||
|
"@solana/web3.js": "^1.90.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,319 @@
|
||||||
|
import { AnchorProvider, Program } from "@coral-xyz/anchor";
|
||||||
|
import { Connection, Signer, VersionedTransaction } from "@solana/web3.js";
|
||||||
|
import {
|
||||||
|
PythSolanaReceiver as PythSolanaReceiverProgram,
|
||||||
|
IDL as Idl,
|
||||||
|
} from "./idl/pyth_solana_receiver";
|
||||||
|
import {
|
||||||
|
WormholeCoreBridgeSolana,
|
||||||
|
IDL as WormholeCoreBridgeSolanaIdl,
|
||||||
|
} from "./idl/wormhole_core_bridge_solana";
|
||||||
|
import {
|
||||||
|
DEFAULT_RECEIVER_PROGRAM_ID,
|
||||||
|
DEFAULT_WORMHOLE_PROGRAM_ID,
|
||||||
|
getConfigPda,
|
||||||
|
getGuardianSetPda,
|
||||||
|
getTreasuryPda,
|
||||||
|
} from "./address";
|
||||||
|
import { PublicKey, Keypair } from "@solana/web3.js";
|
||||||
|
import {
|
||||||
|
parseAccumulatorUpdateData,
|
||||||
|
parsePriceFeedMessage,
|
||||||
|
} from "@pythnetwork/price-service-sdk";
|
||||||
|
import {
|
||||||
|
POST_UPDATE_ATOMIC_COMPUTE_BUDGET,
|
||||||
|
POST_UPDATE_COMPUTE_BUDGET,
|
||||||
|
VERIFY_ENCODED_VAA_COMPUTE_BUDGET,
|
||||||
|
} from "./compute_budget";
|
||||||
|
import { Wallet } from "@coral-xyz/anchor/dist/cjs/provider";
|
||||||
|
import {
|
||||||
|
buildEncodedVaaCreateInstruction,
|
||||||
|
buildWriteEncodedVaaWithSplit,
|
||||||
|
getGuardianSetIndex,
|
||||||
|
trimSignatures,
|
||||||
|
} from "./vaa";
|
||||||
|
import {
|
||||||
|
TransactionBuilder,
|
||||||
|
InstructionWithEphemeralSigners,
|
||||||
|
} from "@pythnetwork/solana-utils";
|
||||||
|
import { PriorityFeeConfig } from "@pythnetwork/solana-utils/lib/transaction";
|
||||||
|
|
||||||
|
export const DEFAULT_TREASURY_ID = 0;
|
||||||
|
|
||||||
|
export class PythSolanaReceiver {
|
||||||
|
readonly connection: Connection;
|
||||||
|
readonly wallet: Wallet;
|
||||||
|
readonly provider: AnchorProvider;
|
||||||
|
readonly receiver: Program<PythSolanaReceiverProgram>;
|
||||||
|
readonly wormhole: Program<WormholeCoreBridgeSolana>;
|
||||||
|
|
||||||
|
constructor({
|
||||||
|
connection,
|
||||||
|
wallet,
|
||||||
|
wormholeProgramId = DEFAULT_WORMHOLE_PROGRAM_ID,
|
||||||
|
receiverProgramId = DEFAULT_RECEIVER_PROGRAM_ID,
|
||||||
|
}: {
|
||||||
|
connection: Connection;
|
||||||
|
wallet: Wallet;
|
||||||
|
wormholeProgramId?: PublicKey;
|
||||||
|
receiverProgramId?: PublicKey;
|
||||||
|
}) {
|
||||||
|
this.connection = connection;
|
||||||
|
this.wallet = wallet;
|
||||||
|
this.provider = new AnchorProvider(this.connection, this.wallet, {
|
||||||
|
commitment: connection.commitment,
|
||||||
|
});
|
||||||
|
this.receiver = new Program<PythSolanaReceiverProgram>(
|
||||||
|
Idl as PythSolanaReceiverProgram,
|
||||||
|
receiverProgramId,
|
||||||
|
this.provider
|
||||||
|
);
|
||||||
|
this.wormhole = new Program<WormholeCoreBridgeSolana>(
|
||||||
|
WormholeCoreBridgeSolanaIdl as WormholeCoreBridgeSolana,
|
||||||
|
wormholeProgramId,
|
||||||
|
this.provider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async withPriceUpdate(
|
||||||
|
priceUpdateDataArray: string[],
|
||||||
|
getInstructions: (
|
||||||
|
priceFeedIdToPriceUpdateAccount: Record<string, PublicKey>
|
||||||
|
) => Promise<InstructionWithEphemeralSigners[]>,
|
||||||
|
priorityFeeConfig?: PriorityFeeConfig
|
||||||
|
): Promise<{ tx: VersionedTransaction; signers: Signer[] }[]> {
|
||||||
|
const {
|
||||||
|
postInstructions,
|
||||||
|
priceFeedIdToPriceUpdateAccount: priceFeedIdToPriceUpdateAccount,
|
||||||
|
cleanupInstructions,
|
||||||
|
} = await this.buildPostPriceUpdateInstructions(priceUpdateDataArray);
|
||||||
|
return TransactionBuilder.batchIntoVersionedTransactions(
|
||||||
|
this.wallet.publicKey,
|
||||||
|
this.connection,
|
||||||
|
[
|
||||||
|
...postInstructions,
|
||||||
|
...(await getInstructions(priceFeedIdToPriceUpdateAccount)),
|
||||||
|
...cleanupInstructions,
|
||||||
|
],
|
||||||
|
priorityFeeConfig ?? {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async withPartiallyVerifiedPriceUpdate(
|
||||||
|
priceUpdateDataArray: string[],
|
||||||
|
getInstructions: (
|
||||||
|
priceFeedIdToPriceUpdateAccount: Record<string, PublicKey>
|
||||||
|
) => Promise<InstructionWithEphemeralSigners[]>,
|
||||||
|
priorityFeeConfig?: PriorityFeeConfig
|
||||||
|
): Promise<{ tx: VersionedTransaction; signers: Signer[] }[]> {
|
||||||
|
const {
|
||||||
|
postInstructions,
|
||||||
|
priceFeedIdToPriceUpdateAccount,
|
||||||
|
cleanupInstructions,
|
||||||
|
} = await this.buildPostPriceUpdateAtomicInstructions(priceUpdateDataArray);
|
||||||
|
return TransactionBuilder.batchIntoVersionedTransactions(
|
||||||
|
this.wallet.publicKey,
|
||||||
|
this.connection,
|
||||||
|
[
|
||||||
|
...postInstructions,
|
||||||
|
...(await getInstructions(priceFeedIdToPriceUpdateAccount)),
|
||||||
|
...cleanupInstructions,
|
||||||
|
],
|
||||||
|
priorityFeeConfig ?? {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildPostPriceUpdateAtomicInstructions(
|
||||||
|
priceUpdateDataArray: string[]
|
||||||
|
): Promise<{
|
||||||
|
postInstructions: InstructionWithEphemeralSigners[];
|
||||||
|
priceFeedIdToPriceUpdateAccount: Record<string, PublicKey>;
|
||||||
|
cleanupInstructions: InstructionWithEphemeralSigners[];
|
||||||
|
}> {
|
||||||
|
const postInstructions: InstructionWithEphemeralSigners[] = [];
|
||||||
|
const priceFeedIdToPriceUpdateAccount: Record<string, PublicKey> = {};
|
||||||
|
const cleanupInstructions: InstructionWithEphemeralSigners[] = [];
|
||||||
|
|
||||||
|
for (const priceUpdateData of priceUpdateDataArray) {
|
||||||
|
const accumulatorUpdateData = parseAccumulatorUpdateData(
|
||||||
|
Buffer.from(priceUpdateData, "base64")
|
||||||
|
);
|
||||||
|
const guardianSetIndex = getGuardianSetIndex(accumulatorUpdateData.vaa);
|
||||||
|
const trimmedVaa = trimSignatures(accumulatorUpdateData.vaa);
|
||||||
|
|
||||||
|
for (const update of accumulatorUpdateData.updates) {
|
||||||
|
const priceUpdateKeypair = new Keypair();
|
||||||
|
postInstructions.push({
|
||||||
|
instruction: await this.receiver.methods
|
||||||
|
.postUpdateAtomic({
|
||||||
|
vaa: trimmedVaa,
|
||||||
|
merklePriceUpdate: update,
|
||||||
|
treasuryId: DEFAULT_TREASURY_ID,
|
||||||
|
})
|
||||||
|
.accounts({
|
||||||
|
priceUpdateAccount: priceUpdateKeypair.publicKey,
|
||||||
|
treasury: getTreasuryPda(DEFAULT_TREASURY_ID),
|
||||||
|
config: getConfigPda(),
|
||||||
|
guardianSet: getGuardianSetPda(guardianSetIndex),
|
||||||
|
})
|
||||||
|
.instruction(),
|
||||||
|
signers: [priceUpdateKeypair],
|
||||||
|
computeUnits: POST_UPDATE_ATOMIC_COMPUTE_BUDGET,
|
||||||
|
});
|
||||||
|
priceFeedIdToPriceUpdateAccount[
|
||||||
|
"0x" + parsePriceFeedMessage(update.message).feedId.toString("hex")
|
||||||
|
] = priceUpdateKeypair.publicKey;
|
||||||
|
|
||||||
|
cleanupInstructions.push(
|
||||||
|
await this.buildClosePriceUpdateInstruction(
|
||||||
|
priceUpdateKeypair.publicKey
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
postInstructions,
|
||||||
|
priceFeedIdToPriceUpdateAccount,
|
||||||
|
cleanupInstructions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildPostEncodedVaaInstructions(vaa: Buffer): Promise<{
|
||||||
|
postInstructions: InstructionWithEphemeralSigners[];
|
||||||
|
encodedVaaAddress: PublicKey;
|
||||||
|
cleanupInstructions: InstructionWithEphemeralSigners[];
|
||||||
|
}> {
|
||||||
|
const postInstructions: InstructionWithEphemeralSigners[] = [];
|
||||||
|
const cleanupInstructions: InstructionWithEphemeralSigners[] = [];
|
||||||
|
const encodedVaaKeypair = new Keypair();
|
||||||
|
const guardianSetIndex = getGuardianSetIndex(vaa);
|
||||||
|
|
||||||
|
postInstructions.push(
|
||||||
|
await buildEncodedVaaCreateInstruction(
|
||||||
|
this.wormhole,
|
||||||
|
vaa,
|
||||||
|
encodedVaaKeypair
|
||||||
|
)
|
||||||
|
);
|
||||||
|
postInstructions.push({
|
||||||
|
instruction: await this.wormhole.methods
|
||||||
|
.initEncodedVaa()
|
||||||
|
.accounts({
|
||||||
|
encodedVaa: encodedVaaKeypair.publicKey,
|
||||||
|
})
|
||||||
|
.instruction(),
|
||||||
|
signers: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
postInstructions.push(
|
||||||
|
...(await buildWriteEncodedVaaWithSplit(
|
||||||
|
this.wormhole,
|
||||||
|
vaa,
|
||||||
|
encodedVaaKeypair.publicKey
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
postInstructions.push({
|
||||||
|
instruction: await this.wormhole.methods
|
||||||
|
.verifyEncodedVaaV1()
|
||||||
|
.accounts({
|
||||||
|
guardianSet: getGuardianSetPda(guardianSetIndex),
|
||||||
|
draftVaa: encodedVaaKeypair.publicKey,
|
||||||
|
})
|
||||||
|
.instruction(),
|
||||||
|
signers: [],
|
||||||
|
computeUnits: VERIFY_ENCODED_VAA_COMPUTE_BUDGET,
|
||||||
|
});
|
||||||
|
|
||||||
|
cleanupInstructions.push(
|
||||||
|
await this.buildCloseEncodedVaaInstruction(encodedVaaKeypair.publicKey)
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
postInstructions,
|
||||||
|
encodedVaaAddress: encodedVaaKeypair.publicKey,
|
||||||
|
cleanupInstructions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildPostPriceUpdateInstructions(
|
||||||
|
priceUpdateDataArray: string[]
|
||||||
|
): Promise<{
|
||||||
|
postInstructions: InstructionWithEphemeralSigners[];
|
||||||
|
priceFeedIdToPriceUpdateAccount: Record<string, PublicKey>;
|
||||||
|
cleanupInstructions: InstructionWithEphemeralSigners[];
|
||||||
|
}> {
|
||||||
|
const postInstructions: InstructionWithEphemeralSigners[] = [];
|
||||||
|
const priceFeedIdToPriceUpdateAccount: Record<string, PublicKey> = {};
|
||||||
|
const cleanupInstructions: InstructionWithEphemeralSigners[] = [];
|
||||||
|
|
||||||
|
for (const priceUpdateData of priceUpdateDataArray) {
|
||||||
|
const accumulatorUpdateData = parseAccumulatorUpdateData(
|
||||||
|
Buffer.from(priceUpdateData, "base64")
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
postInstructions: postEncodedVaaInstructions,
|
||||||
|
encodedVaaAddress: encodedVaa,
|
||||||
|
cleanupInstructions: postEncodedVaaCleanupInstructions,
|
||||||
|
} = await this.buildPostEncodedVaaInstructions(accumulatorUpdateData.vaa);
|
||||||
|
postInstructions.push(...postEncodedVaaInstructions);
|
||||||
|
cleanupInstructions.push(...postEncodedVaaCleanupInstructions);
|
||||||
|
|
||||||
|
for (const update of accumulatorUpdateData.updates) {
|
||||||
|
const priceUpdateKeypair = new Keypair();
|
||||||
|
postInstructions.push({
|
||||||
|
instruction: await this.receiver.methods
|
||||||
|
.postUpdate({
|
||||||
|
merklePriceUpdate: update,
|
||||||
|
treasuryId: DEFAULT_TREASURY_ID,
|
||||||
|
})
|
||||||
|
.accounts({
|
||||||
|
encodedVaa,
|
||||||
|
priceUpdateAccount: priceUpdateKeypair.publicKey,
|
||||||
|
treasury: getTreasuryPda(DEFAULT_TREASURY_ID),
|
||||||
|
config: getConfigPda(),
|
||||||
|
})
|
||||||
|
.instruction(),
|
||||||
|
signers: [priceUpdateKeypair],
|
||||||
|
computeUnits: POST_UPDATE_COMPUTE_BUDGET,
|
||||||
|
});
|
||||||
|
|
||||||
|
priceFeedIdToPriceUpdateAccount[
|
||||||
|
"0x" + parsePriceFeedMessage(update.message).feedId.toString("hex")
|
||||||
|
] = priceUpdateKeypair.publicKey;
|
||||||
|
cleanupInstructions.push(
|
||||||
|
await this.buildClosePriceUpdateInstruction(
|
||||||
|
priceUpdateKeypair.publicKey
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
postInstructions,
|
||||||
|
priceFeedIdToPriceUpdateAccount,
|
||||||
|
cleanupInstructions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildCloseEncodedVaaInstruction(
|
||||||
|
encodedVaa: PublicKey
|
||||||
|
): Promise<InstructionWithEphemeralSigners> {
|
||||||
|
const instruction = await this.wormhole.methods
|
||||||
|
.closeEncodedVaa()
|
||||||
|
.accounts({ encodedVaa })
|
||||||
|
.instruction();
|
||||||
|
return { instruction, signers: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildClosePriceUpdateInstruction(
|
||||||
|
priceUpdateAccount: PublicKey
|
||||||
|
): Promise<InstructionWithEphemeralSigners> {
|
||||||
|
const instruction = await this.receiver.methods
|
||||||
|
.reclaimRent()
|
||||||
|
.accounts({ priceUpdateAccount })
|
||||||
|
.instruction();
|
||||||
|
return { instruction, signers: [] };
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { PublicKey } from "@solana/web3.js";
|
||||||
|
|
||||||
|
export const DEFAULT_RECEIVER_PROGRAM_ID = new PublicKey(
|
||||||
|
"rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ"
|
||||||
|
);
|
||||||
|
export const DEFAULT_WORMHOLE_PROGRAM_ID = new PublicKey(
|
||||||
|
"HDwcJBJXjL9FpJ7UBsYBtaDjsBUhuLCUYoz3zr8SWWaQ"
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getGuardianSetPda = (guardianSetIndex: number) => {
|
||||||
|
const guardianSetIndexBuf = Buffer.alloc(4);
|
||||||
|
guardianSetIndexBuf.writeUInt32BE(guardianSetIndex, 0);
|
||||||
|
return PublicKey.findProgramAddressSync(
|
||||||
|
[Buffer.from("GuardianSet"), guardianSetIndexBuf],
|
||||||
|
DEFAULT_WORMHOLE_PROGRAM_ID
|
||||||
|
)[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTreasuryPda = (treasuryId: number) => {
|
||||||
|
return PublicKey.findProgramAddressSync(
|
||||||
|
[Buffer.from("treasury"), Buffer.from([treasuryId])],
|
||||||
|
DEFAULT_RECEIVER_PROGRAM_ID
|
||||||
|
)[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getConfigPda = () => {
|
||||||
|
return PublicKey.findProgramAddressSync(
|
||||||
|
[Buffer.from("config")],
|
||||||
|
DEFAULT_RECEIVER_PROGRAM_ID
|
||||||
|
)[0];
|
||||||
|
};
|
|
@ -0,0 +1,3 @@
|
||||||
|
export const VERIFY_ENCODED_VAA_COMPUTE_BUDGET = 400000;
|
||||||
|
export const POST_UPDATE_ATOMIC_COMPUTE_BUDGET = 400000;
|
||||||
|
export const POST_UPDATE_COMPUTE_BUDGET = 200000;
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,2 @@
|
||||||
|
export { PythSolanaReceiver } from "./PythSolanaReceiver";
|
||||||
|
export { TransactionBuilder } from "@pythnetwork/solana-utils";
|
|
@ -0,0 +1,81 @@
|
||||||
|
import { Keypair, PublicKey } from "@solana/web3.js";
|
||||||
|
import { WormholeCoreBridgeSolana } from "./idl/wormhole_core_bridge_solana";
|
||||||
|
import { Program } from "@coral-xyz/anchor";
|
||||||
|
import { InstructionWithEphemeralSigners } from "@pythnetwork/solana-utils";
|
||||||
|
|
||||||
|
export const VAA_START = 46;
|
||||||
|
export const VAA_SIGNATURE_SIZE = 66;
|
||||||
|
export const VAA_SPLIT_INDEX = 792;
|
||||||
|
export const DEFAULT_REDUCED_GUARDIAN_SET_SIZE = 5;
|
||||||
|
|
||||||
|
export function getGuardianSetIndex(vaa: Buffer) {
|
||||||
|
return vaa.readUInt32BE(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function trimSignatures(
|
||||||
|
vaa: Buffer,
|
||||||
|
n = DEFAULT_REDUCED_GUARDIAN_SET_SIZE
|
||||||
|
): Buffer {
|
||||||
|
const currentNumSignatures = vaa[5];
|
||||||
|
if (n > currentNumSignatures) {
|
||||||
|
throw new Error(
|
||||||
|
"Resulting VAA can't have more signatures than the original VAA"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const trimmedVaa = Buffer.concat([
|
||||||
|
vaa.subarray(0, 6 + n * VAA_SIGNATURE_SIZE),
|
||||||
|
vaa.subarray(6 + currentNumSignatures * VAA_SIGNATURE_SIZE),
|
||||||
|
]);
|
||||||
|
|
||||||
|
trimmedVaa[5] = n;
|
||||||
|
return trimmedVaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function buildEncodedVaaCreateInstruction(
|
||||||
|
wormhole: Program<WormholeCoreBridgeSolana>,
|
||||||
|
vaa: Buffer,
|
||||||
|
encodedVaaKeypair: Keypair
|
||||||
|
) {
|
||||||
|
const encodedVaaSize = vaa.length + VAA_START;
|
||||||
|
return {
|
||||||
|
instruction: await wormhole.account.encodedVaa.createInstruction(
|
||||||
|
encodedVaaKeypair,
|
||||||
|
encodedVaaSize
|
||||||
|
),
|
||||||
|
signers: [encodedVaaKeypair],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function buildWriteEncodedVaaWithSplit(
|
||||||
|
wormhole: Program<WormholeCoreBridgeSolana>,
|
||||||
|
vaa: Buffer,
|
||||||
|
draftVaa: PublicKey
|
||||||
|
): Promise<InstructionWithEphemeralSigners[]> {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
instruction: await wormhole.methods
|
||||||
|
.writeEncodedVaa({
|
||||||
|
index: 0,
|
||||||
|
data: vaa.subarray(0, VAA_SPLIT_INDEX),
|
||||||
|
})
|
||||||
|
.accounts({
|
||||||
|
draftVaa,
|
||||||
|
})
|
||||||
|
.instruction(),
|
||||||
|
signers: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instruction: await wormhole.methods
|
||||||
|
.writeEncodedVaa({
|
||||||
|
index: VAA_SPLIT_INDEX,
|
||||||
|
data: vaa.subarray(VAA_SPLIT_INDEX),
|
||||||
|
})
|
||||||
|
.accounts({
|
||||||
|
draftVaa,
|
||||||
|
})
|
||||||
|
.instruction(),
|
||||||
|
signers: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../../../tsconfig.base.json",
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.json"],
|
||||||
|
"exclude": ["node_modules", "**/__tests__/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "src/",
|
||||||
|
"outDir": "./lib"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
plugins: ["@typescript-eslint"],
|
||||||
|
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
||||||
|
module.exports = {
|
||||||
|
preset: "ts-jest",
|
||||||
|
testEnvironment: "node",
|
||||||
|
};
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"name": "@pythnetwork/solana-utils",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Utility functions for Solana",
|
||||||
|
"homepage": "https://pyth.network",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"types": "lib/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"lib/**/*"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/pyth-network/pyth-crosschain.git",
|
||||||
|
"directory": "target_chains/solana/sdk/js/solana_utils"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest",
|
||||||
|
"build": "tsc",
|
||||||
|
"format": "prettier --write \"src/**/*.ts\"",
|
||||||
|
"lint": "eslint src/",
|
||||||
|
"prepublishOnly": "npm run build && npm test && npm run lint",
|
||||||
|
"preversion": "npm run lint",
|
||||||
|
"version": "npm run format && git add -A src"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"pyth",
|
||||||
|
"oracle"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^29.4.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.20.0",
|
||||||
|
"@typescript-eslint/parser": "^5.20.0",
|
||||||
|
"eslint": "^8.13.0",
|
||||||
|
"jest": "^29.4.0",
|
||||||
|
"prettier": "^2.6.2",
|
||||||
|
"quicktype": "^23.0.76",
|
||||||
|
"ts-jest": "^29.0.5",
|
||||||
|
"typescript": "^4.6.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@solana/web3.js": "^1.90.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
import {
|
||||||
|
ComputeBudgetProgram,
|
||||||
|
Keypair,
|
||||||
|
PublicKey,
|
||||||
|
SystemProgram,
|
||||||
|
Transaction,
|
||||||
|
TransactionInstruction,
|
||||||
|
TransactionMessage,
|
||||||
|
VersionedTransaction,
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import { getSizeOfCompressedU16, getSizeOfTransaction } from "..";
|
||||||
|
|
||||||
|
it("Unit test compressed u16 size", async () => {
|
||||||
|
expect(getSizeOfCompressedU16(127)).toBe(1);
|
||||||
|
expect(getSizeOfCompressedU16(128)).toBe(2);
|
||||||
|
expect(getSizeOfCompressedU16(16383)).toBe(2);
|
||||||
|
expect(getSizeOfCompressedU16(16384)).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Unit test for getSizeOfTransaction", async () => {
|
||||||
|
jest.setTimeout(60000);
|
||||||
|
|
||||||
|
const payer = new Keypair();
|
||||||
|
|
||||||
|
const ixsToSend: TransactionInstruction[] = [];
|
||||||
|
|
||||||
|
ixsToSend.push(
|
||||||
|
SystemProgram.createAccount({
|
||||||
|
fromPubkey: payer.publicKey,
|
||||||
|
newAccountPubkey: PublicKey.unique(),
|
||||||
|
space: 100,
|
||||||
|
lamports: 1000000000,
|
||||||
|
programId: SystemProgram.programId,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
ixsToSend.push(
|
||||||
|
SystemProgram.createAccountWithSeed({
|
||||||
|
fromPubkey: PublicKey.unique(),
|
||||||
|
basePubkey: PublicKey.unique(),
|
||||||
|
seed: "seed",
|
||||||
|
newAccountPubkey: PublicKey.unique(),
|
||||||
|
space: 100,
|
||||||
|
lamports: 1000000000,
|
||||||
|
programId: SystemProgram.programId,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
ixsToSend.push(
|
||||||
|
new TransactionInstruction({
|
||||||
|
keys: [{ pubkey: PublicKey.unique(), isSigner: true, isWritable: true }],
|
||||||
|
programId: PublicKey.unique(),
|
||||||
|
data: Buffer.from([1, 2, 3]),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
ixsToSend.push(ComputeBudgetProgram.setComputeUnitLimit({ units: 69 }));
|
||||||
|
|
||||||
|
ixsToSend.push(
|
||||||
|
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1000000 })
|
||||||
|
);
|
||||||
|
|
||||||
|
const transaction = new Transaction();
|
||||||
|
for (const ix of ixsToSend) {
|
||||||
|
transaction.add(ix);
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.recentBlockhash = "GqdFtdM7zzWw33YyHtBNwPhyBsdYKcfm9gT47bWnbHvs"; // Mock blockhash from devnet
|
||||||
|
transaction.feePayer = payer.publicKey;
|
||||||
|
expect(transaction.serialize({ requireAllSignatures: false }).length).toBe(
|
||||||
|
getSizeOfTransaction(ixsToSend, false)
|
||||||
|
);
|
||||||
|
|
||||||
|
const versionedTransaction = new VersionedTransaction(
|
||||||
|
new TransactionMessage({
|
||||||
|
recentBlockhash: transaction.recentBlockhash,
|
||||||
|
payerKey: payer.publicKey,
|
||||||
|
instructions: ixsToSend,
|
||||||
|
}).compileToV0Message()
|
||||||
|
);
|
||||||
|
expect(versionedTransaction.serialize().length).toBe(
|
||||||
|
getSizeOfTransaction(ixsToSend)
|
||||||
|
);
|
||||||
|
});
|
|
@ -0,0 +1,6 @@
|
||||||
|
export {
|
||||||
|
getSizeOfTransaction,
|
||||||
|
getSizeOfCompressedU16,
|
||||||
|
TransactionBuilder,
|
||||||
|
InstructionWithEphemeralSigners,
|
||||||
|
} from "./transaction";
|
|
@ -0,0 +1,226 @@
|
||||||
|
import {
|
||||||
|
ComputeBudgetProgram,
|
||||||
|
Connection,
|
||||||
|
PACKET_DATA_SIZE,
|
||||||
|
PublicKey,
|
||||||
|
Signer,
|
||||||
|
Transaction,
|
||||||
|
TransactionInstruction,
|
||||||
|
TransactionMessage,
|
||||||
|
VersionedTransaction,
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
|
||||||
|
export const DEFAULT_COMPUTE_BUDGET_UNITS = 200000;
|
||||||
|
export const PACKET_DATA_SIZE_WITH_ROOM_FOR_COMPUTE_BUDGET =
|
||||||
|
PACKET_DATA_SIZE - 52;
|
||||||
|
|
||||||
|
export type InstructionWithEphemeralSigners = {
|
||||||
|
instruction: TransactionInstruction;
|
||||||
|
signers: Signer[];
|
||||||
|
computeUnits?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PriorityFeeConfig = {
|
||||||
|
computeUnitPriceMicroLamports?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size of a transaction that would contain the provided array of instructions
|
||||||
|
*/
|
||||||
|
export function getSizeOfTransaction(
|
||||||
|
instructions: TransactionInstruction[],
|
||||||
|
versionedTransaction = true
|
||||||
|
): number {
|
||||||
|
const signers = new Set<string>();
|
||||||
|
const accounts = new Set<string>();
|
||||||
|
|
||||||
|
instructions.map((ix) => {
|
||||||
|
accounts.add(ix.programId.toBase58()),
|
||||||
|
ix.keys.map((key) => {
|
||||||
|
if (key.isSigner) {
|
||||||
|
signers.add(key.pubkey.toBase58());
|
||||||
|
}
|
||||||
|
accounts.add(key.pubkey.toBase58());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const instruction_sizes: number = instructions
|
||||||
|
.map(
|
||||||
|
(ix) =>
|
||||||
|
1 +
|
||||||
|
getSizeOfCompressedU16(ix.keys.length) +
|
||||||
|
ix.keys.length +
|
||||||
|
getSizeOfCompressedU16(ix.data.length) +
|
||||||
|
ix.data.length
|
||||||
|
)
|
||||||
|
.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
1 +
|
||||||
|
signers.size * 64 +
|
||||||
|
3 +
|
||||||
|
getSizeOfCompressedU16(accounts.size) +
|
||||||
|
32 * accounts.size +
|
||||||
|
32 +
|
||||||
|
getSizeOfCompressedU16(instructions.length) +
|
||||||
|
instruction_sizes +
|
||||||
|
(versionedTransaction ? 1 + getSizeOfCompressedU16(0) : 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size of n in bytes when serialized as a CompressedU16
|
||||||
|
*/
|
||||||
|
export function getSizeOfCompressedU16(n: number) {
|
||||||
|
return 1 + Number(n >= 128) + Number(n >= 16384);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is helpful for batching instructions into transactions in an efficient way.
|
||||||
|
* As you add instructions, it adds them to the current transactions until it's full, then it starts a new transaction.
|
||||||
|
*/
|
||||||
|
export class TransactionBuilder {
|
||||||
|
readonly transactionInstructions: {
|
||||||
|
instructions: TransactionInstruction[];
|
||||||
|
signers: Signer[];
|
||||||
|
computeUnits: number;
|
||||||
|
}[] = [];
|
||||||
|
readonly payer: PublicKey;
|
||||||
|
readonly connection: Connection;
|
||||||
|
|
||||||
|
constructor(payer: PublicKey, connection: Connection) {
|
||||||
|
this.payer = payer;
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an instruction to the builder, the signers argument can be used to specify ephemeral signers that need to sign the transaction
|
||||||
|
* where this instruction appears
|
||||||
|
*/
|
||||||
|
addInstruction(args: InstructionWithEphemeralSigners) {
|
||||||
|
const { instruction, signers, computeUnits } = args;
|
||||||
|
if (this.transactionInstructions.length === 0) {
|
||||||
|
this.transactionInstructions.push({
|
||||||
|
instructions: [instruction],
|
||||||
|
signers: signers,
|
||||||
|
computeUnits: computeUnits ?? 0,
|
||||||
|
});
|
||||||
|
} else if (
|
||||||
|
getSizeOfTransaction([
|
||||||
|
...this.transactionInstructions[this.transactionInstructions.length - 1]
|
||||||
|
.instructions,
|
||||||
|
instruction,
|
||||||
|
]) <= PACKET_DATA_SIZE_WITH_ROOM_FOR_COMPUTE_BUDGET
|
||||||
|
) {
|
||||||
|
this.transactionInstructions[
|
||||||
|
this.transactionInstructions.length - 1
|
||||||
|
].instructions.push(instruction);
|
||||||
|
this.transactionInstructions[
|
||||||
|
this.transactionInstructions.length - 1
|
||||||
|
].signers.push(...signers);
|
||||||
|
this.transactionInstructions[
|
||||||
|
this.transactionInstructions.length - 1
|
||||||
|
].computeUnits += computeUnits ?? 0;
|
||||||
|
} else
|
||||||
|
this.transactionInstructions.push({
|
||||||
|
instructions: [instruction],
|
||||||
|
signers: signers,
|
||||||
|
computeUnits: computeUnits ?? 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addInstructions(instructions: InstructionWithEphemeralSigners[]) {
|
||||||
|
for (const { instruction, signers, computeUnits } of instructions) {
|
||||||
|
this.addInstruction({ instruction, signers, computeUnits });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the added instructions batched into transactions, plus for each transaction the ephemeral signers that need to sign it
|
||||||
|
*/
|
||||||
|
async getVersionedTransactions(
|
||||||
|
args: PriorityFeeConfig
|
||||||
|
): Promise<{ tx: VersionedTransaction; signers: Signer[] }[]> {
|
||||||
|
const blockhash = (await this.connection.getLatestBlockhash()).blockhash;
|
||||||
|
|
||||||
|
return this.transactionInstructions.map(
|
||||||
|
({ instructions, signers, computeUnits }) => {
|
||||||
|
const instructionsWithComputeBudget: TransactionInstruction[] = [
|
||||||
|
...instructions,
|
||||||
|
];
|
||||||
|
if (computeUnits > DEFAULT_COMPUTE_BUDGET_UNITS * instructions.length) {
|
||||||
|
instructionsWithComputeBudget.push(
|
||||||
|
ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (args.computeUnitPriceMicroLamports) {
|
||||||
|
instructionsWithComputeBudget.push(
|
||||||
|
ComputeBudgetProgram.setComputeUnitPrice({
|
||||||
|
microLamports: args.computeUnitPriceMicroLamports,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
tx: new VersionedTransaction(
|
||||||
|
new TransactionMessage({
|
||||||
|
recentBlockhash: blockhash,
|
||||||
|
instructions: instructionsWithComputeBudget,
|
||||||
|
payerKey: this.payer,
|
||||||
|
}).compileToV0Message()
|
||||||
|
),
|
||||||
|
signers: signers,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the added instructions batched into transactions, plus for each transaction the ephemeral signers that need to sign it
|
||||||
|
*/
|
||||||
|
getLegacyTransactions(
|
||||||
|
args: PriorityFeeConfig
|
||||||
|
): { tx: Transaction; signers: Signer[] }[] {
|
||||||
|
return this.transactionInstructions.map(({ instructions, signers }) => {
|
||||||
|
const instructionsWithComputeBudget = args.computeUnitPriceMicroLamports
|
||||||
|
? [
|
||||||
|
...instructions,
|
||||||
|
ComputeBudgetProgram.setComputeUnitPrice({
|
||||||
|
microLamports: args.computeUnitPriceMicroLamports,
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
: instructions;
|
||||||
|
|
||||||
|
return {
|
||||||
|
tx: new Transaction().add(...instructionsWithComputeBudget),
|
||||||
|
signers: signers,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static batchIntoLegacyTransactions(
|
||||||
|
instructions: TransactionInstruction[]
|
||||||
|
): Transaction[] {
|
||||||
|
const transactionBuilder = new TransactionBuilder(
|
||||||
|
PublicKey.unique(),
|
||||||
|
new Connection("http://placeholder.placeholder")
|
||||||
|
); // We only need wallet and connection for `VersionedTransaction` so we can put placeholders here
|
||||||
|
for (const instruction of instructions) {
|
||||||
|
transactionBuilder.addInstruction({ instruction, signers: [] });
|
||||||
|
}
|
||||||
|
return transactionBuilder.getLegacyTransactions({}).map(({ tx }) => {
|
||||||
|
return tx;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static async batchIntoVersionedTransactions(
|
||||||
|
payer: PublicKey,
|
||||||
|
connection: Connection,
|
||||||
|
instructions: InstructionWithEphemeralSigners[],
|
||||||
|
priorityFeeConfig: PriorityFeeConfig
|
||||||
|
): Promise<{ tx: VersionedTransaction; signers: Signer[] }[]> {
|
||||||
|
const transactionBuilder = new TransactionBuilder(payer, connection);
|
||||||
|
transactionBuilder.addInstructions(instructions);
|
||||||
|
return transactionBuilder.getVersionedTransactions(priorityFeeConfig);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../../../tsconfig.base.json",
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.json"],
|
||||||
|
"exclude": ["node_modules", "**/__tests__/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "src/",
|
||||||
|
"outDir": "./lib"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue