Skip to content

Commit 1c3bc7b

Browse files
committed
update mapping account size, add support for update price
1 parent fc513f0 commit 1c3bc7b

File tree

5 files changed

+120
-8
lines changed

5 files changed

+120
-8
lines changed

program_admin/__init__.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ async def fetch_minimum_balance(self, size: int) -> int:
114114

115115
async def refresh_program_accounts(self):
116116
async with AsyncClient(self.rpc_endpoint) as client:
117-
logger.info("Refreshing program accounts")
117+
logger.info(f"Refreshing program accounts for {self.program_key}")
118118
result = (
119119
await client.get_program_accounts(
120120
pubkey=self.program_key,
@@ -395,7 +395,7 @@ async def sync_mapping_instructions(
395395
)
396396
)
397397

398-
logger.debug("Building pyth_program.init_mapping instruction")
398+
logger.debug(f"Building pyth_program.init_mapping instruction: {funding_keypair.public_key}, {mapping_0_keypair.public_key}")
399399
instructions.append(
400400
pyth_program.init_mapping(
401401
self.program_key,
@@ -603,6 +603,30 @@ async def sync_price_instructions(
603603

604604
return (instructions, [funding_keypair, price_keypair])
605605

606+
607+
def update_price_instructions(
608+
self,
609+
publisher_keypair: Keypair,
610+
price_pubkey: PublicKey,
611+
price: int,
612+
confidence: int,
613+
price_slot: int
614+
) -> Tuple[List[TransactionInstruction], List[Keypair]]:
615+
instructions = []
616+
instructions.append(
617+
pyth_program.upd_price(
618+
self.program_key,
619+
publisher_keypair.public_key,
620+
price_pubkey,
621+
1,
622+
price,
623+
confidence,
624+
price_slot
625+
)
626+
)
627+
return (instructions, [publisher_keypair])
628+
629+
606630
async def sync_authority_permissions_instructions(
607631
self,
608632
reference_authority_permissions: ReferenceAuthorityPermissions,

program_admin/cli.py

+37-3
Original file line numberDiff line numberDiff line change
@@ -297,23 +297,29 @@ def list_accounts(network, rpc_endpoint, program_key, keys, publishers, commitme
297297

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

302303
if product_account.data.first_price_account_key != PublicKey(0):
303304
price_account = program_admin.get_price_account(
304305
product_account.data.first_price_account_key
305306
)
307+
print(f" Price Account: {price_account.public_key}")
306308
print(
307309
f" Price: {price_account.data.exponent} exponent ({price_account.data.components_count} components)"
308310
)
311+
print(f" numPublishers: {price_account.data.components_count}")
312+
print(f" numPrices: {price_account.data.quoters_count}")
313+
print(f" numComponents: {len(price_account.data.price_components)}")
314+
print(f" Aggregate: {price_account.data.aggregate}")
309315

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

316-
print(f" Publisher: {name}")
322+
print(f" Publisher: {name}: {component.latest_price} {component.aggregate_price}")
317323

318324
mapping_key = mapping_account.data.next_mapping_account_key
319325

@@ -462,11 +468,9 @@ def sync(
462468
ref_permissions = parse_permissions_with_overrides(
463469
Path(permissions), Path(overrides), network
464470
)
465-
466471
ref_authority_permissions = parse_authority_permissions_json(
467472
Path(authority_permissions)
468473
)
469-
470474
asyncio.run(
471475
program_admin.sync(
472476
ref_products=ref_products,
@@ -479,6 +483,35 @@ def sync(
479483
)
480484
)
481485

486+
@click.command()
487+
@click.option("--network", help="Solana network", envvar="NETWORK")
488+
@click.option("--rpc-endpoint", help="Solana RPC endpoint", envvar="RPC_ENDPOINT")
489+
@click.option("--program-key", help="Pyth program key", envvar="PROGRAM_KEY")
490+
@click.option("--keys", help="Path to keys directory", envvar="KEYS")
491+
@click.option("--publisher", help="key file of the publisher")
492+
@click.option("--price-account", help="Public key of the price account")
493+
@click.option("--price", help="Price to set")
494+
@click.option("--price-slot", help="Price slot to set")
495+
def update_price(network, rpc_endpoint, program_key, keys, publisher, price_account, price, price_slot):
496+
program_admin = ProgramAdmin(
497+
network=network,
498+
rpc_endpoint=rpc_endpoint,
499+
key_dir=keys,
500+
program_key=program_key,
501+
price_store_key=None,
502+
commitment="confirmed",
503+
)
504+
publisher_keypair = load_keypair(publisher, key_dir=keys)
505+
price_account = PublicKey(price_account)
506+
(instructions, signers, ) = program_admin.update_price_instructions(
507+
publisher_keypair,
508+
price_account,
509+
int(price),
510+
100,
511+
int(price_slot)
512+
)
513+
asyncio.run(program_admin.send_transaction(instructions, signers))
514+
482515

483516
@click.command()
484517
@click.option("--network", help="Solana network", envvar="NETWORK")
@@ -578,5 +611,6 @@ def resize_price_accounts_v2(
578611
cli.add_command(update_product_metadata)
579612
cli.add_command(migrate_upgrade_authority)
580613
cli.add_command(resize_price_accounts_v2)
614+
cli.add_command(update_price)
581615
logger.remove()
582616
logger.add(sys.stdout, serialize=(not os.environ.get("DEV_MODE")))

program_admin/instructions.py

+56-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from typing import Dict
22

3-
from construct import Bytes, Int32sl, Int32ul, Struct
3+
from construct import Bytes, Int32sl, Int32ul, Struct, Int64sl
44
from solana.publickey import PublicKey
55
from solana.system_program import SYS_PROGRAM_ID
6+
from solana.sysvar import SYSVAR_CLOCK_PUBKEY
67
from solana.transaction import AccountMeta, TransactionInstruction
78

89
from program_admin.types import ReferenceAuthorityPermissions
@@ -16,6 +17,8 @@
1617
COMMAND_ADD_PRICE = 4
1718
COMMAND_ADD_PUBLISHER = 5
1819
COMMAND_DEL_PUBLISHER = 6
20+
COMMAND_UPD_PRICE = 7
21+
COMMAND_INIT_PRICE = 9
1922
COMMAND_MIN_PUBLISHERS = 12
2023
COMMAND_RESIZE_PRICE_ACCOUNT = 14
2124
COMMAND_DEL_PRICE = 15
@@ -297,6 +300,58 @@ def toggle_publisher(
297300
)
298301

299302

303+
def init_price(
304+
program_key: PublicKey,
305+
funding_key: PublicKey,
306+
price_account_key: PublicKey,
307+
) -> TransactionInstruction:
308+
layout = Struct(
309+
"version" / Int32ul, "command" / Int32sl, "exponent" / Int32sl, "type" / Int32ul
310+
)
311+
data = layout.build(
312+
dict(version=PROGRAM_VERSION, command=COMMAND_INIT_PRICE, exponent=8, type=PRICE_TYPE_PRICE)
313+
)
314+
315+
permissions_account = get_permissions_account(
316+
program_key, AUTHORITY_PERMISSIONS_PDA_SEED
317+
)
318+
319+
return TransactionInstruction(
320+
data=data,
321+
keys=[
322+
AccountMeta(pubkey=funding_key, is_signer=True, is_writable=True),
323+
AccountMeta(pubkey=price_account_key, is_signer=True, is_writable=True),
324+
AccountMeta(pubkey=permissions_account, is_signer=False, is_writable=True),
325+
],
326+
program_id=program_key,
327+
)
328+
329+
def upd_price(
330+
program_key: PublicKey,
331+
funding_key: PublicKey,
332+
price_account_key: PublicKey,
333+
status: int,
334+
price: int,
335+
confidence: int,
336+
publish_slot: int
337+
) -> TransactionInstruction:
338+
layout = Struct(
339+
"version" / Int32ul, "command" / Int32sl, "status" / Int32sl, "unused" / Int32sl, "price" / Int64sl, "confidence" / Int64sl, "publish_slot" / Int64sl
340+
)
341+
data = layout.build(
342+
dict(version=PROGRAM_VERSION, command=COMMAND_UPD_PRICE, unused=0, status=status, price=price, confidence=confidence, publish_slot=publish_slot)
343+
)
344+
345+
return TransactionInstruction(
346+
data=data,
347+
keys=[
348+
AccountMeta(pubkey=funding_key, is_signer=True, is_writable=True),
349+
AccountMeta(pubkey=price_account_key, is_signer=False, is_writable=True),
350+
AccountMeta(pubkey=SYSVAR_CLOCK_PUBKEY, is_signer=False, is_writable=False),
351+
],
352+
program_id=program_key,
353+
)
354+
300355
def upd_permissions(
301356
program_key: PublicKey,
302357
upgrade_authority: PublicKey,

program_admin/keys.py

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ def load_keypair(
3939
return Keypair.from_secret_key(data)
4040
else:
4141
file_path = Path(key_dir) / f"{label_or_pubkey}.json"
42-
4342
if not file_path.exists():
4443
if generate:
4544
return generate_keypair(label_or_pubkey, key_dir)

program_admin/util.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
ReferencePermissions,
1515
)
1616

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

0 commit comments

Comments
 (0)