Price Feed IDs for tokens on Sonic SVM

Hi team, I’m currently building a defi dApp on Sonic that needs price feed feature.

I tried to search for Price Feed IDs for tokens on Sonic SVM but cannot find any.

Please help me to check if any price feed IDs available on Sonic or can we add for some popular tokens (SOL, SONIC, USDT, USDC, … )

We have all price feeds available on Sonic SVM.

Please follow this guide to start integrating Pyth on Sonic SVM.

Following links will help you get started.
Price Feed IDs.
Sonic Receiver and Price Feed accounts
SVM Price Feed Accounts

In Sonic Explorer, I tried to search with a SONIC feed ID from SVM Price Feed Accounts but it says:

Account doesn’t exist

So, I’m not sure if it can be used in our Sonic contract

Gm @haongo138 , looks like no one has pushed a price update for that feed before. Please follow the example that @Aditya520 shared above to post an update and fetch the account where it’s stored. Also, keep in mind that the account is derived from the feed ID and the shard (default 0). You can edit the shard number in the example and see that the update gets posted to a different account.

2 Likes

Thanks @tejas_pyth, I’m trying to run price pusher but cannot submit the transaction (it’s keep retrying until timeout)

Here’s the logs:

 pnpm run start solana \
  --endpoint https://api.mainnet-alpha.sonic.game \
  --keypair-file ~/.config/solana/id.json \
  --shard-id 0 \
  --price-config-file ./price-config.yaml \
  --price-service-endpoint https://hermes.pyth.network/ \
  --pyth-contract-address pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT \
  --pushing-frequency 30 \
  --polling-frequency 5

> @pythnetwork/price-pusher@9.3.1 start /Users/antono/workspace/yolofi/pyth-crosschain/apps/price_pusher
> node lib/index.js solana --endpoint https\://api.mainnet-alpha.sonic.game --keypair-file /Users/antono/.config/solana/id.json --shard-id 0 --price-config-file ./price-config.yaml --price-service-endpoint https\://hermes.pyth.network/ --pyth-contract-address pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT --pushing-frequency 30 --polling-frequency 5

using deprecated parameters for the initialization function; pass a single object instead
Warning: fragment with name GasCostsFragment already exists.
graphql-tag enforces all fragment names across your application to be unique; read more about
this in the docs: http://dev.apollodata.com/core/fragments.html#unique-names
Warning: fragment with name chainInfoFragment already exists.
graphql-tag enforces all fragment names across your application to be unique; read more about
this in the docs: http://dev.apollodata.com/core/fragments.html#unique-names
{"level":30,"time":1745917132856,"pid":8820,"hostname":"192.168.1.9.non-exists.ptr.local","msg":"Metrics server started on port 9090"}
{"level":30,"time":1745917132891,"pid":8820,"hostname":"192.168.1.9.non-exists.ptr.local","module":"Metrics","msg":"Metrics server started on port 9090"}
{"level":30,"time":1745917167009,"pid":8820,"hostname":"192.168.1.9.non-exists.ptr.local","module":"Controller","msg":"SONIC/USD (b2748e718cf3a75b0ca099cb467aea6aa8f7d960b381b3970769b5a2d6be26dc) is not available on the target network. Pushing the price."}
{"level":30,"time":1745917167009,"pid":8820,"hostname":"192.168.1.9.non-exists.ptr.local","module":"Controller","msg":"PYTH/USD (0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff) is not available on the target network. Pushing the price."}
{"level":30,"time":1745917167009,"pid":8820,"hostname":"192.168.1.9.non-exists.ptr.local","module":"Controller","msg":"USDC/USD (eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a) is not available on the target network. Pushing the price."}
{"level":30,"time":1745917167009,"pid":8820,"hostname":"192.168.1.9.non-exists.ptr.local","module":"Controller","msg":"USDT/USD (2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b) is not available on the target network. Pushing the price."}
{"level":30,"time":1745917167009,"pid":8820,"hostname":"192.168.1.9.non-exists.ptr.local","module":"Controller","priceIds":[{"id":"b2748e718cf3a75b0ca099cb467aea6aa8f7d960b381b3970769b5a2d6be26dc","alias":"SONIC/USD"},{"id":"0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff","alias":"PYTH/USD"},{"id":"eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a","alias":"USDC/USD"},{"id":"2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b","alias":"USDT/USD"}],"msg":"Some of the checks triggered pushing update. Will push the updates for some feeds."}
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  0
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  1
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  2
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  3
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  4
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  5
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  6
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  7
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  8
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  9
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  10
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  11
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  12
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  13
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  14
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  15
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  16
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  17
Retrying transaction  0  of  4  with signature:  5YA3vy94fiQBGCxMCVhCdKyJcApXubYUvSaReyGHRGQSuDa1pSykLNe3aPxZp1mJ4asLEdv8apuP6FbF5nC9chQN  Retry count:  18

This is my price config file:

- alias: SONIC/USD
  id: '0xb2748e718cf3a75b0ca099cb467aea6aa8f7d960b381b3970769b5a2d6be26dc'
  time_difference: 60
  price_deviation: 0.5
  confidence_ratio: 1
  early_update:
    time_difference: 30
    price_deviation: 0.5
    confidence_ratio: 0.1
- alias: PYTH/USD
  id: '0x0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff'
  time_difference: 60
  price_deviation: 1
  confidence_ratio: 1
  early_update:
    time_difference: 30
    price_deviation: 0.5
    confidence_ratio: 0.1
- alias: USDC/USD
  id: '0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a'
  time_difference: 60
  price_deviation: 0.5
  confidence_ratio: 1
- alias: USDT/USD
  id: '0x2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b'
  time_difference: 60
  price_deviation: 0.5
  confidence_ratio: 1

Hi @tejas_pyth @Aditya520, I can push the price feed now.

But do you know the Oracle address of USDC/USD feed in Sonic Testnet, I can see this address Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD in Pyth Network, it does exist in Solscan but doesn’t exist in Sonic testnet explorer?

Gm @haongo138 glad you got the pusher working! The address of a price feed is derived from the price feed ID and the shard ID (default 0). You can see the derivation here. Thus, it will be the same address on testnet and mainnet.

You can run the update_price_feeds.ts example with pnpm exec ts-node examples/update_price_feed.ts to see which address a certain price feed will get posted to.

The address will not exist if the price feed has never been pushed to before with the given shard id (default 0.) I pushed an update to the USDC feed in Sonic Testnet as an example: 91LF2K1yGkwpePM43yctMX1BGwf6atSFgjcPnNYG8czx

Thanks @tejas_pyth a lot for this knowledge,

From other discussion, I can see that Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD is a base58 version of price feed id 0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a

When I configured oracle for my Marginfi bank using these values, my config script worked:

  • SOL_ORACLE → Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD
  • SOL_ORACLE_FEED → Dpw1EAVrSB1ibxiDQyTAW6Zip3J4Btk2x4SgApQCeFbX (from Price Feed IDs | Pyth Network)

But if I change SOL_ORACLE to the address 91LF2K1yGkwpePM43yctMX1BGwf6atSFgjcPnNYG8czx you deployed, run script again, it throws Invalid Pyth account

Seems there a connection between SOL_ORACLE & SOL_ORACLE_FEED, do you know about this?

In my case, it would be the best now if we can have Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD available on Sonic Testnet like this Solscan one

Ah I see there’s some confusion here. I’m not familiar with Marginfi so you may need to check with them on this, but SOL_ORACLE likely refers to the pubkey of the Pyth Push Oracle, which can be found here: https://docs.pyth.network/price-feeds/contract-addresses/solana

I don’t see SOL_ORACLE_FEED actually being used in your config script?
But you can use the feed account from here: 7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE

Please see this doc on how to use price feed accounts: https://docs.pyth.network/price-feeds/use-real-time-data/solana#price-feed-accounts

I don’t see SOL_ORACLE_FEED actually being used in your config script?

@tejas_pyth Ah, when I ran the script, it requires remainingAccounts when calling the instruction, so I passed it there as oracleMeta, then the script ran fine.

....
const config: Config = {
  PROGRAM_ID: "4ktkTCjsHh1VdqwqkXBjGqZKnBkycWZMe3AEXEcdSbwV",
  GROUP_KEY: new PublicKey("5XSQ5Zxhe4VG6qwvsJPu5ZVsWgcfTYFQMsXoZFhnhNW7"),
  BANK: new PublicKey("GQ7qTwK4WJ3Gi6ZCtpuDGcbLSSaXrgPfDJmT5K1ZQSR1"),
  SOL_ORACLE: new PublicKey("Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD"),
  SOL_ORACLE_FEED: new PublicKey("Dpw1EAVrSB1ibxiDQyTAW6Zip3J4Btk2x4SgApQCeFbX"),
  ADMIN: new PublicKey("4ai4tdtEsanxqhuVg1BXCsHYyQPgG3rPsE99sCGoaks8"),

  MULTISIG_PAYER: new PublicKey("4ai4tdtEsanxqhuVg1BXCsHYyQPgG3rPsE99sCGoaks8"),
};

const oracleMeta: AccountMeta = {
  pubkey: config.SOL_ORACLE_FEED,
  isSigner: false,
  isWritable: false,
};

async function main() {
  marginfiIdl.address = config.PROGRAM_ID;
  const connection = new Connection(process.env.PRIVATE_RPC_ENDPOINT, "confirmed");
  const wallet = loadKeypairFromFile(process.env.MARGINFI_WALLET);

  // @ts-ignore
  const provider = new AnchorProvider(connection, wallet, {
    preflightCommitment: "confirmed",
  });

  const program = new Program<Marginfi>(marginfiIdl as Marginfi, provider);

  const transaction = new Transaction();

  transaction.add(
    await program.methods
      .lendingPoolConfigureBankOracle(3, config.SOL_ORACLE)
      .accountsPartial({
        // group: config.GROUP_KEY,
        admin: config.ADMIN,
        bank: config.BANK,
      })
      .remainingAccounts([oracleMeta])
      .instruction()
  );
....

note: Ignores the variable name, in above code, both SOL_ORACLE & SOL_ORACLE_FEED, which I used, are pointing to USDC price feed

In the meantime, let me try connecting Marginfi team.

Additionally, as this explaination, SOL_ORACLE is a price feed account from the legacy version of Pyth, do you have plan to sunset it or possibly make it available in SVM?

Hi @tejas_pyth, I just found from this docs, each feed has two accounts:

  • a product account stores metadata
  • a price account stores a list of authorized data providers for this specific price feed

So in my code above, SOL_ORACLE means the price account, do you know how can I deploy it onto Sonic SVM chain?

Hey @haongo138 yeah, I’d recommend you contact the Marginfi team for support here since we aren’t able to provide detailed help with Marginfi contracts.

I recall you have a pusher working, please refer to this doc for pushing and consuming the SOL feed on Sonic: https://docs.pyth.network/price-feeds/use-real-time-data/solana#price-feed-accounts