Skip to content

Commit

Permalink
update mapping account size, add support for update price
Browse files Browse the repository at this point in the history
  • Loading branch information
mingdourolabs committed Mar 5, 2025
1 parent fc513f0 commit 1c3bc7b
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 8 deletions.
28 changes: 26 additions & 2 deletions program_admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ async def fetch_minimum_balance(self, size: int) -> int:

async def refresh_program_accounts(self):
async with AsyncClient(self.rpc_endpoint) as client:
logger.info("Refreshing program accounts")
logger.info(f"Refreshing program accounts for {self.program_key}")
result = (
await client.get_program_accounts(
pubkey=self.program_key,
Expand Down Expand Up @@ -395,7 +395,7 @@ async def sync_mapping_instructions(
)
)

logger.debug("Building pyth_program.init_mapping instruction")
logger.debug(f"Building pyth_program.init_mapping instruction: {funding_keypair.public_key}, {mapping_0_keypair.public_key}")
instructions.append(
pyth_program.init_mapping(
self.program_key,
Expand Down Expand Up @@ -603,6 +603,30 @@ async def sync_price_instructions(

return (instructions, [funding_keypair, price_keypair])


def update_price_instructions(
self,
publisher_keypair: Keypair,
price_pubkey: PublicKey,
price: int,
confidence: int,
price_slot: int
) -> Tuple[List[TransactionInstruction], List[Keypair]]:
instructions = []
instructions.append(
pyth_program.upd_price(
self.program_key,
publisher_keypair.public_key,
price_pubkey,
1,
price,
confidence,
price_slot
)
)
return (instructions, [publisher_keypair])


async def sync_authority_permissions_instructions(
self,
reference_authority_permissions: ReferenceAuthorityPermissions,
Expand Down
40 changes: 37 additions & 3 deletions program_admin/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,23 +297,29 @@ def list_accounts(network, rpc_endpoint, program_key, keys, publishers, commitme

for product_key in mapping_account.data.product_account_keys:
product_account = program_admin.get_product_account(product_key)
print(f" Product Public Key: {product_account.public_key}")
print(f" Product: {product_account.data.metadata['symbol']}")

if product_account.data.first_price_account_key != PublicKey(0):
price_account = program_admin.get_price_account(
product_account.data.first_price_account_key
)
print(f" Price Account: {price_account.public_key}")
print(
f" Price: {price_account.data.exponent} exponent ({price_account.data.components_count} components)"
)
print(f" numPublishers: {price_account.data.components_count}")
print(f" numPrices: {price_account.data.quoters_count}")
print(f" numComponents: {len(price_account.data.price_components)}")
print(f" Aggregate: {price_account.data.aggregate}")

for component in price_account.data.price_components:
try:
name = publishers_map["names"][component.publisher_key]
except KeyError:
name = f"??? ({component.publisher_key})"

print(f" Publisher: {name}")
print(f" Publisher: {name}: {component.latest_price} {component.aggregate_price}")

mapping_key = mapping_account.data.next_mapping_account_key

Expand Down Expand Up @@ -462,11 +468,9 @@ def sync(
ref_permissions = parse_permissions_with_overrides(
Path(permissions), Path(overrides), network
)

ref_authority_permissions = parse_authority_permissions_json(
Path(authority_permissions)
)

asyncio.run(
program_admin.sync(
ref_products=ref_products,
Expand All @@ -479,6 +483,35 @@ def sync(
)
)

@click.command()
@click.option("--network", help="Solana network", envvar="NETWORK")
@click.option("--rpc-endpoint", help="Solana RPC endpoint", envvar="RPC_ENDPOINT")
@click.option("--program-key", help="Pyth program key", envvar="PROGRAM_KEY")
@click.option("--keys", help="Path to keys directory", envvar="KEYS")
@click.option("--publisher", help="key file of the publisher")
@click.option("--price-account", help="Public key of the price account")
@click.option("--price", help="Price to set")
@click.option("--price-slot", help="Price slot to set")
def update_price(network, rpc_endpoint, program_key, keys, publisher, price_account, price, price_slot):
program_admin = ProgramAdmin(
network=network,
rpc_endpoint=rpc_endpoint,
key_dir=keys,
program_key=program_key,
price_store_key=None,
commitment="confirmed",
)
publisher_keypair = load_keypair(publisher, key_dir=keys)
price_account = PublicKey(price_account)
(instructions, signers, ) = program_admin.update_price_instructions(
publisher_keypair,
price_account,
int(price),
100,
int(price_slot)
)
asyncio.run(program_admin.send_transaction(instructions, signers))


@click.command()
@click.option("--network", help="Solana network", envvar="NETWORK")
Expand Down Expand Up @@ -578,5 +611,6 @@ def resize_price_accounts_v2(
cli.add_command(update_product_metadata)
cli.add_command(migrate_upgrade_authority)
cli.add_command(resize_price_accounts_v2)
cli.add_command(update_price)
logger.remove()
logger.add(sys.stdout, serialize=(not os.environ.get("DEV_MODE")))
57 changes: 56 additions & 1 deletion program_admin/instructions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from typing import Dict

from construct import Bytes, Int32sl, Int32ul, Struct
from construct import Bytes, Int32sl, Int32ul, Struct, Int64sl
from solana.publickey import PublicKey
from solana.system_program import SYS_PROGRAM_ID
from solana.sysvar import SYSVAR_CLOCK_PUBKEY
from solana.transaction import AccountMeta, TransactionInstruction

from program_admin.types import ReferenceAuthorityPermissions
Expand All @@ -16,6 +17,8 @@
COMMAND_ADD_PRICE = 4
COMMAND_ADD_PUBLISHER = 5
COMMAND_DEL_PUBLISHER = 6
COMMAND_UPD_PRICE = 7
COMMAND_INIT_PRICE = 9
COMMAND_MIN_PUBLISHERS = 12
COMMAND_RESIZE_PRICE_ACCOUNT = 14
COMMAND_DEL_PRICE = 15
Expand Down Expand Up @@ -297,6 +300,58 @@ def toggle_publisher(
)


def init_price(
program_key: PublicKey,
funding_key: PublicKey,
price_account_key: PublicKey,
) -> TransactionInstruction:
layout = Struct(
"version" / Int32ul, "command" / Int32sl, "exponent" / Int32sl, "type" / Int32ul
)
data = layout.build(
dict(version=PROGRAM_VERSION, command=COMMAND_INIT_PRICE, exponent=8, type=PRICE_TYPE_PRICE)
)

permissions_account = get_permissions_account(
program_key, AUTHORITY_PERMISSIONS_PDA_SEED
)

return TransactionInstruction(
data=data,
keys=[
AccountMeta(pubkey=funding_key, is_signer=True, is_writable=True),
AccountMeta(pubkey=price_account_key, is_signer=True, is_writable=True),
AccountMeta(pubkey=permissions_account, is_signer=False, is_writable=True),
],
program_id=program_key,
)

def upd_price(
program_key: PublicKey,
funding_key: PublicKey,
price_account_key: PublicKey,
status: int,
price: int,
confidence: int,
publish_slot: int
) -> TransactionInstruction:
layout = Struct(
"version" / Int32ul, "command" / Int32sl, "status" / Int32sl, "unused" / Int32sl, "price" / Int64sl, "confidence" / Int64sl, "publish_slot" / Int64sl
)
data = layout.build(
dict(version=PROGRAM_VERSION, command=COMMAND_UPD_PRICE, unused=0, status=status, price=price, confidence=confidence, publish_slot=publish_slot)
)

return TransactionInstruction(
data=data,
keys=[
AccountMeta(pubkey=funding_key, is_signer=True, is_writable=True),
AccountMeta(pubkey=price_account_key, is_signer=False, is_writable=True),
AccountMeta(pubkey=SYSVAR_CLOCK_PUBKEY, is_signer=False, is_writable=False),
],
program_id=program_key,
)

def upd_permissions(
program_key: PublicKey,
upgrade_authority: PublicKey,
Expand Down
1 change: 0 additions & 1 deletion program_admin/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ def load_keypair(
return Keypair.from_secret_key(data)
else:
file_path = Path(key_dir) / f"{label_or_pubkey}.json"

if not file_path.exists():
if generate:
return generate_keypair(label_or_pubkey, key_dir)
Expand Down
2 changes: 1 addition & 1 deletion program_admin/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
ReferencePermissions,
)

MAPPING_ACCOUNT_SIZE = 20536 # https://github.com/pyth-network/pyth-client/blob/b49f73afe32ce8685a3d05e32d8f3bb51909b061/program/src/oracle/oracle.h#L88
MAPPING_ACCOUNT_SIZE = 160056 # https://github.com/pyth-network/pyth-client/blob/main/program/c/src/oracle/oracle.h#L120
MAPPING_ACCOUNT_PRODUCT_LIMIT = 640
PRICE_ACCOUNT_V1_SIZE = 3312
PRICE_ACCOUNT_V2_SIZE = 12576
Expand Down

0 comments on commit 1c3bc7b

Please sign in to comment.